diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh index 8768f472..d8a8b21f 100644 --- a/.clusterfuzzlite/build.sh +++ b/.clusterfuzzlite/build.sh @@ -23,6 +23,10 @@ for dir in harness/*; do mv "${dir}/${zip_name}" "${OUT}" fi done + +# Copy libFuzzer dictionaries so clusterfuzzlite auto-loads .dict next to the binary +cp harness/fuzz_sign_transaction.dict "${OUT}/" 2>/dev/null || true + cmake --build build mv ./build/fuzz_* "${OUT}" popd diff --git a/APP_SPECIFICATION.md b/APP_SPECIFICATION.md index 971ab4bb..9fca513e 100644 --- a/APP_SPECIFICATION.md +++ b/APP_SPECIFICATION.md @@ -80,6 +80,49 @@ None [Description](doc/SIGN_TRANSACTION.md) +## Supported credits.aleo functions for clear-signing + +The device performs clear-signed review screens only for the following +`credits.aleo` functions. Any other function name causes the signing flow to +return `SWO_INCORRECT_DATA`. + +### Transfer functions + +| Function name | Review subtitle | Fields shown on device | +| --------------------------- | -------------------------------------------- | --------------------------------------- | +| `transfer_public` | "Public transfer" | Amount, To (address), Fees | +| `transfer_private` | "Private transfer" | Amount, To (address), Fees | +| `transfer_public_to_private`| "Transfer from public to private address" | Amount, To (address), Fees | +| `transfer_private_to_public`| "Transfer from private to public address" | Amount, To (address), Fees | + +### Fee functions (auto-approved, no interactive review screen) + +| Function name | Behaviour | +| -------------- | ---------------------------------------------------- | +| `fee_public` | Automatically signed; no screen shown to the user. | +| `fee_private` | Automatically signed; no screen shown to the user. | + +### Staking functions + +These three functions map to `TX_STAKING` and display the "Review staking +transaction?" screen. + +| Function name | Review subtitle | Fields shown on device | +| ---------------------- | --------------- | --------------------------------------------------------------------- | +| `bond_public` | "Stake ALEO" | Validator (address), Payout to / withdrawal (address), Amount, Fees | +| `unbond_public` | "Unstake ALEO" | Staker (address), Amount, Fees | +| `claim_unbond_public` | "Claim ALEO" | Staker (address), Fees *(no Amount field — claim has no amount)* | + +All amounts are displayed in ALEO (microcredits converted by +`EXPONENT_SMALLEST_UNIT` = 6 decimal places). Fees shown are +`max_base_fee + max_priority_fee`. + +### Other functions recognised by the BHP-1024 parameter table + +`split` and `join` are present in `bhp_1024_parameters.c` for function-ID +verification purposes but are not dispatched to a review screen by the current +firmware; they return `SWO_INCORRECT_DATA` if presented as a root transaction. + ## STATUS WORDS The following standard Status Words are returned for all APDUs. diff --git a/Makefile b/Makefile index adb0f186..86f5952d 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ APPNAME = "Aleo" # Application version APPVERSION_M = 1 -APPVERSION_N = 2 +APPVERSION_N = 3 APPVERSION_P = 0 APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" diff --git a/fuzzing/README.md b/fuzzing/README.md index 87b7dd21..7e553528 100644 --- a/fuzzing/README.md +++ b/fuzzing/README.md @@ -140,3 +140,34 @@ docker run --rm --privileged -e FUZZING_LANGUAGE=c -v "$(realpath .)/fuzzing/out ```bash docker run --rm --privileged -e FUZZING_ENGINE=libfuzzer -e RUN_FUZZER_MODE=interactive -v "$(realpath .)/fuzzing/corpus:/tmp/fuzz_corpus" -v "$(realpath .)/fuzzing/out:/out" -ti gcr.io/oss-fuzz-base/base-runner run_fuzzer fuzzer ``` + +## Seed corpus and dictionary for `fuzz_sign_transaction` + +### Seed corpus + +Seed inputs live in `fuzzing/harness/fuzz_sign_transaction/` (one binary file per seed). +`build.sh` automatically zips that directory into `fuzz_sign_transaction_seed_corpus.zip` and +copies it to `$OUT`, where clusterfuzzlite picks it up on the first run. + +To regenerate or extend the seeds locally: + +```bash +cd fuzzing +python3 gen_seeds.py +``` + +### libFuzzer dictionary + +`fuzzing/harness/fuzz_sign_transaction.dict` contains meaningful tokens for the TLV wire format: +function-name strings (`transfer_public`, `bond_public`, …), TLV type bytes (`\xb6` for +FUNCTION_NAME, `\xb4` for REQUEST, etc.) and common input-type tag sequences (address/u64, +public/private visibility). + +`build.sh` copies the dictionary to `$OUT/fuzz_sign_transaction.dict`; clusterfuzzlite and +oss-fuzz automatically load a file named `.dict` placed next to the binary. + +To use the dictionary during a local run: + +```bash +build/fuzz_sign_transaction -dict=harness/fuzz_sign_transaction.dict [corpus_dir] +``` diff --git a/fuzzing/gen_seeds.py b/fuzzing/gen_seeds.py new file mode 100644 index 00000000..775f1fb6 --- /dev/null +++ b/fuzzing/gen_seeds.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +""" +Generate the libFuzzer seed corpus for fuzz_sign_transaction. + +Each seed is the raw APDU DATA stream (5-byte header stripped from every chunk +and concatenated) for one sign-transaction interaction. Seeds are written one +binary file per case into fuzzing/harness/fuzz_sign_transaction/; build.sh zips +that directory into the seed corpus that clusterfuzzlite loads on first run. + +Requires Python >= 3.9 (the reused test client uses PEP 585 generics): + cd fuzzing && python3 gen_seeds.py +""" + +import os +import sys + +# Reuse the functional-test client so seeds match real APDU encoding. +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +TESTS_DIR = os.path.join(os.path.dirname(SCRIPT_DIR), "tests") +sys.path.insert(0, TESTS_DIR) + +from application_client.transaction import Transaction # noqa: E402 + +OUT_DIR = os.path.join(SCRIPT_DIR, "harness", "fuzz_sign_transaction") +os.makedirs(OUT_DIR, exist_ok=True) + +# Test vectors (mirror tests/standalone/test_sign_transaction.py). +PATH = "m/44'/683'/0'/0'" +ADDR = "aleo1sfydt6z6cnqjx3hcgk9ajw03ecj6uqlfcm9u3p3gdhckzcc2w5xqv3v3pe" +ADDR_WITHDRAW = "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px" +RECORD = [ + "3614797564276936744957924747041031196891698846785520060979425601577054464500field", + "2426895214035216932245297778850989035038538961658726507442215877484415082794field", + "0220642863446832956019507279394572297489712696240584424406852292692897199577field", +] +EXEC_ID = "7266375125414209082394925781071362722506946030314916664133746682226945366259field" + + +def _request(function_name: str, inputs: list) -> dict: + return { + 'network_id': 'mainnet', 'program_id': 'credits.aleo', + 'function_name': function_name, 'inputs': inputs, + 'nested_call_count': 0, 'program_checksum': '', + } + + +def intent(function_name: str, inputs: list, fee_function_name: str) -> dict: + return { + 'type': 'intent', 'path': PATH, + 'max_base_fee': 500, 'max_priority_fee': 100, + 'fee_program_id': 'credits.aleo', 'fee_function_name': fee_function_name, + 'request': _request(function_name, inputs), + } + + +def fee(function_name: str, inputs: list) -> dict: + return {'type': 'fee', 'request': _request(function_name, inputs)} + + +CASES = { + 'bond_public': intent('bond_public', [ + {'type': 'address.public', 'value': ADDR}, + {'type': 'address.public', 'value': ADDR_WITHDRAW}, + {'type': 'u64.public', 'value': 10000000000}, + ], 'fee_public'), + 'unbond_public': intent('unbond_public', [ + {'type': 'address.public', 'value': ADDR}, + {'type': 'u64.public', 'value': 5000000000}, + ], 'fee_public'), + 'claim_unbond_public': intent('claim_unbond_public', [ + {'type': 'address.public', 'value': ADDR}, + ], 'fee_public'), + 'transfer_public': intent('transfer_public', [ + {'type': 'address.public', 'value': ADDR}, + {'type': 'u64.public', 'value': 1000}, + ], 'fee_public'), + 'transfer_private': intent('transfer_private', [ + {'type': 'credits.record', 'value': RECORD}, + {'type': 'address.private', 'value': ADDR}, + {'type': 'u64.private', 'value': 1000}, + ], 'fee_private'), + 'fee_public': fee('fee_public', [ + {'type': 'u64.public', 'value': 500}, + {'type': 'u64.public', 'value': 100}, + {'type': 'field.public', 'value': EXEC_ID}, + ]), + 'fee_private': fee('fee_private', [ + {'type': 'credits.record', 'value': RECORD}, + {'type': 'u64.public', 'value': 500}, + {'type': 'u64.public', 'value': 100}, + {'type': 'field.public', 'value': EXEC_ID}, + ]), +} + +HEADER_HEX_CHARS = 10 # CLA INS P1 P2 Lc = 5 bytes + + +def apdus_to_seed(apdus: list) -> bytes: + """Strip the 5-byte header from each APDU chunk and concatenate the payload.""" + return bytes.fromhex("".join(apdu[HEADER_HEX_CHARS:] for apdu in apdus)) + + +for name, tx in CASES.items(): + seed = apdus_to_seed(Transaction().gen_apdus_tx(tx)) + with open(os.path.join(OUT_DIR, f"seed_{name}"), "wb") as f: + f.write(seed) + print(f"seed_{name}: {len(seed)} bytes") + +print(f"\n{len(CASES)} seeds written to {OUT_DIR}") diff --git a/fuzzing/harness/fuzz_sign_transaction.dict b/fuzzing/harness/fuzz_sign_transaction.dict new file mode 100644 index 00000000..a54ede99 --- /dev/null +++ b/fuzzing/harness/fuzz_sign_transaction.dict @@ -0,0 +1,64 @@ +# libFuzzer dictionary for fuzz_sign_transaction +# Function names recognised by tx_parse.c (credits.aleo program_id + one of these triggers a parse path) +"transfer_public" +"transfer_private" +"transfer_public_to_private" +"transfer_private_to_public" +"fee_public" +"fee_private" +"bond_public" +"unbond_public" +"claim_unbond_public" +"credits.aleo" + +# TLV type bytes (single-byte tags encoded with 0x81 long-form prefix in the wire format) +# Tags <= 0x7f are encoded directly; tags 0x80-0xff use the 0x81 two-byte form. +# STRUCTURE_TYPE=0x01, VERSION=0x02 (short-form tags) +"\x01" +"\x02" +# SIGNATURE=0x15 +"\x15" +# Long-form tag prefix used for all 0x80+ tags +"\x81" +# MAX_BASE_FEE=0xb0, MAX_PRIORITY_FEE=0xb1 +"\xb0" +"\xb1" +# FEE_FUNCTION_NAME=0xb2, FEE_PROGRAM_ID=0xb3 +"\xb2" +"\xb3" +# REQUEST=0xb4, PROGRAM_ID=0xb5 +"\xb4" +"\xb5" +# FUNCTION_NAME=0xb6, INPUT_COUNT=0xb7 +"\xb6" +"\xb7" +# INPUT_VALUES=0xb8, INPUT_TYPES=0xb9, NESTED_CALL_COUNT=0xba +"\xb8" +"\xb9" +"\xba" +# NETWORK_ID=0xc3, PROGRAM_CHECKSUM=0xc4 +"\xc3" +"\xc4" + +# Input-type tag sequences (3-byte prefix encoding: visibility | plaintext-kind | literal-type) +# address.public -> 0x01 (public) 0x00 (plaintext) 0x00 (literal address) +"\x01\x00\x00" +# address.private -> 0x02 (private) 0x00 (plaintext) 0x00 (literal address) +"\x02\x00\x00" +# u64.public -> 0x01 (public) 0x00 (plaintext) 0x0c (literal u64) +"\x01\x00\x0c" +# u64.private -> 0x02 (private) 0x00 (plaintext) 0x0c (literal u64) +"\x02\x00\x0c" +# record input -> 0x03 (record) prefix +"\x03" + +# Tokens auto-discovered by libFuzzer (recommended dictionary from a 78M-run session). +# High-use byte sequences that drove new coverage — mostly u64 boundary values. +# zero / two-byte zero pad +"\x00\x00" +# u64 little-endian == 1 +"\x01\x00" +# u64 little-endian == 2 +"\x02\x00\x00\x00\x00\x00\x00\x00" +# u64 == 0xFFFFFFFFFFFFFFFF (max / -1) +"\xff\xff\xff\xff\xff\xff\xff\xff" diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_bond_public b/fuzzing/harness/fuzz_sign_transaction/seed_bond_public new file mode 100644 index 00000000..75dc992b Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_bond_public differ diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_claim_unbond_public b/fuzzing/harness/fuzz_sign_transaction/seed_claim_unbond_public new file mode 100644 index 00000000..be797a59 Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_claim_unbond_public differ diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_fee_private b/fuzzing/harness/fuzz_sign_transaction/seed_fee_private new file mode 100644 index 00000000..495495b9 Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_fee_private differ diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_fee_public b/fuzzing/harness/fuzz_sign_transaction/seed_fee_public new file mode 100644 index 00000000..b2e94c76 Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_fee_public differ diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_transfer_private b/fuzzing/harness/fuzz_sign_transaction/seed_transfer_private new file mode 100644 index 00000000..b47c11e5 Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_transfer_private differ diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_transfer_public b/fuzzing/harness/fuzz_sign_transaction/seed_transfer_public new file mode 100644 index 00000000..350bdb66 Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_transfer_public differ diff --git a/fuzzing/harness/fuzz_sign_transaction/seed_unbond_public b/fuzzing/harness/fuzz_sign_transaction/seed_unbond_public new file mode 100644 index 00000000..326fd957 Binary files /dev/null and b/fuzzing/harness/fuzz_sign_transaction/seed_unbond_public differ diff --git a/src/db/db_program_function.c b/src/db/db_program_function.c index 02eaf513..72d16cf5 100644 --- a/src/db/db_program_function.c +++ b/src/db/db_program_function.c @@ -17,7 +17,7 @@ #include "db_program_function.h" -#define NB_OF_CREDITS_ALEO_FUNCTIONS (8) +#define NB_OF_CREDITS_ALEO_FUNCTIONS (11) const function_parameters_t credits_aleo[NB_OF_CREDITS_ALEO_FUNCTIONS] = { {.name = "transfer_public", .tx_type = TX_ALEO_TRANSFER_PUBLIC, @@ -83,6 +83,30 @@ const function_parameters_t credits_aleo[NB_OF_CREDITS_ALEO_FUNCTIONS] = { = {0xb56e347d9733de05, 0x29c0febaeb2bee52, 0x6c4d0ed1285f19fd, 0x0ec48ec3bdf25eb8}}, {.big.u64 = {0x921936604e6eddfe, 0x429d23effcfce58b, 0x072b665308c3d12b, 0x1241fcb49a8a9b72}}}}, + {.name = "bond_public", + .tx_type = TX_STAKING, + .input_count = 3, + .bhp_1024_hashes + = {{.big.u64 + = {0xfad1870949c8aa5f, 0xb94139693a1a9ede, 0x13826b9d3dda98ed, 0x11692029f1d694e3}}, + {.big.u64 + = {0x11e14f163d3f2b7c, 0xc591f619d35fb0ab, 0x3456c789125b6f67, 0x0eec83be57f64f40}}}}, + {.name = "unbond_public", + .tx_type = TX_STAKING, + .input_count = 2, + .bhp_1024_hashes + = {{.big.u64 + = {0x7023ecbf86089ad7, 0x1d8626b632ad9001, 0x9f1706e883708361, 0x029c23c1fc2b9465}}, + {.big.u64 + = {0x75ca6051e895980f, 0x86110aa6b233d58e, 0x53106280baec89af, 0x0628c9c0bfeaeb79}}}}, + {.name = "claim_unbond_public", + .tx_type = TX_STAKING, + .input_count = 1, + .bhp_1024_hashes + = {{.big.u64 + = {0x44e8eea54a97db6b, 0x137b370eeb14174b, 0xb14498709cf52fb5, 0x10df36004e953eb8}}, + {.big.u64 + = {0xe506d14510bc7c88, 0xb5566ac3133fe094, 0x8c7852dcca7e24e1, 0x0bce73be56cbba46}}}}, }; #define NB_OF_LDG_P_28_ALEO_FUNCTIONS (7) diff --git a/src/transaction/tx_parse.c b/src/transaction/tx_parse.c index 4793574c..7ff099db 100644 --- a/src/transaction/tx_parse.c +++ b/src/transaction/tx_parse.c @@ -63,6 +63,9 @@ static int parse_token_batch_transfer_private_to_public(sign_transaction_datas_t static int parse_fee_public(sign_transaction_datas_t *data, tx_t *tx); static int parse_fee_private(sign_transaction_datas_t *data, tx_t *tx); +static int parse_bond_public(sign_transaction_datas_t *data, tx_t *tx); +static int parse_unbond_public(sign_transaction_datas_t *data, tx_t *tx); +static int parse_claim_unbond_public(sign_transaction_datas_t *data, tx_t *tx); static int get_u64(input_t *input, bool is_private, uint64_t *value) { @@ -386,6 +389,43 @@ static int parse_fee_private(sign_transaction_datas_t *data, tx_t *tx) return status; } +static int parse_bond_public(sign_transaction_datas_t *data, tx_t *tx) +{ + // TODO: (decide on that) + // NOTE: bond_public's on-chain finalize asserts caller != validator (and a + // minimum bond of 1 ALEO). Both are locally checkable on-device (we hold the + // signer address and the validator input at index 0), but per ADR004 §12 they + // are intentionally NOT rejected here for now: the device is a trusted-display + // passthrough signer and lets on-chain finalize stay authoritative. + tx->staking.type = TX_STAKING_BOND; + int status = get_address(&data->prepared_request.inputs[0], false, tx->staking.validator); + if (status == 0) { + status = get_address(&data->prepared_request.inputs[1], false, tx->staking.withdrawal); + } + if (status == 0) { + status = get_u64(&data->prepared_request.inputs[2], false, &tx->staking.amount); + } + + return status; +} + +static int parse_unbond_public(sign_transaction_datas_t *data, tx_t *tx) +{ + tx->staking.type = TX_STAKING_UNBOND; + int status = get_address(&data->prepared_request.inputs[0], false, tx->staking.staker); + if (status == 0) { + status = get_u64(&data->prepared_request.inputs[1], false, &tx->staking.amount); + } + + return status; +} + +static int parse_claim_unbond_public(sign_transaction_datas_t *data, tx_t *tx) +{ + tx->staking.type = TX_STAKING_CLAIM; + return get_address(&data->prepared_request.inputs[0], false, tx->staking.staker); +} + int tx_parse(sign_transaction_datas_t *data, tx_t *tx) { LEDGER_ASSERT(data != NULL, "NULL data"); @@ -471,6 +511,23 @@ int tx_parse(sign_transaction_datas_t *data, tx_t *tx) G_context.r_list.count = 0; return parse_fee_private(data, tx); + case TX_STAKING: + G_context.r_list.count = 0; + if ((data->prepared_request.function_name_length == 11) + && !memcmp(data->prepared_request.function_name, "bond_public", 11)) { + return parse_bond_public(data, tx); + } + else if ((data->prepared_request.function_name_length == 13) + && !memcmp(data->prepared_request.function_name, "unbond_public", 13)) { + return parse_unbond_public(data, tx); + } + else if ((data->prepared_request.function_name_length == 19) + && !memcmp( + data->prepared_request.function_name, "claim_unbond_public", 19)) { + return parse_claim_unbond_public(data, tx); + } + return -1; + default: break; } diff --git a/src/types.h b/src/types.h index dc09f13c..0a62b881 100644 --- a/src/types.h +++ b/src/types.h @@ -118,6 +118,7 @@ typedef struct { typedef enum { TX_UNKNOWN, + TX_STAKING, TX_SPLIT, TX_JOIN, TX_TOKEN_JOIN, @@ -149,6 +150,12 @@ typedef struct { uint8_t decimals; } token_display_info_t; +typedef enum { + TX_STAKING_BOND, + TX_STAKING_UNBOND, + TX_STAKING_CLAIM, +} tx_staking_type_e; + typedef struct { char address_to[ADDRESS_LEN + 1]; u128_t amount; @@ -160,10 +167,19 @@ typedef struct { uint64_t priority_fee; } tx_fee_t; +typedef struct { + tx_staking_type_e type; + char validator[ADDRESS_LEN + 1]; // bond only + char withdrawal[ADDRESS_LEN + 1]; // bond only + char staker[ADDRESS_LEN + 1]; // unbond / claim + uint64_t amount; // bond / unbond (claim leaves unset) +} tx_staking_t; + typedef struct { tx_type_e type; tx_transfer_t transfer; tx_fee_t fee; + tx_staking_t staking; } tx_t; /** diff --git a/src/ui/nbgl_display_transaction.c b/src/ui/nbgl_display_transaction.c index 6add96bb..16eb85f2 100644 --- a/src/ui/nbgl_display_transaction.c +++ b/src/ui/nbgl_display_transaction.c @@ -43,10 +43,22 @@ static char g_amount_fees[MAX_AMOUNT_SIZE + 4]; // Ticker is ALEO for fees static char g_finish_title[27 + 1 + MAX_TICKER_SIZE]; static char g_review_title[29 + 1 + MAX_TICKER_SIZE]; -// The flow with the most pairs to display is the token signing flow with amount + dest + token -static nbgl_contentTagValue_t pairs[3]; +// Tag/value rows for the review screen; +// Remember to increase pairs[] when a transaction type needs more fields. +static nbgl_contentTagValue_t pairs[4]; static nbgl_contentTagValueList_t pairList; +static int format_aleo_amount(char *dest, size_t dest_size, uint64_t amount) +{ + char tmp[50 + MAX_TICKER_SIZE]; + explicit_bzero(dest, dest_size); + if (!format_fpu64(tmp, sizeof(tmp), amount, EXPONENT_SMALLEST_UNIT)) { + return -1; + } + snprintf(dest, dest_size, "%.*s ALEO", (int) strlen(tmp), tmp); + return 0; +} + static void review_transaction(bool confirm) { validate_transaction(confirm); @@ -77,6 +89,95 @@ static void review_transaction(bool confirm) } } +static int display_review_staking(void) +{ + uint8_t pair_index = 0; + const char *review_subtitle = NULL; + + if (G_context.tx.staking.type == TX_STAKING_BOND) { + review_subtitle = "Stake ALEO"; + } + else if (G_context.tx.staking.type == TX_STAKING_UNBOND) { + review_subtitle = "Unstake ALEO"; + } + else if (G_context.tx.staking.type == TX_STAKING_CLAIM) { + review_subtitle = "Claim ALEO"; + } + else { + return io_send_sw(SWO_INCORRECT_DATA); + } + + // Format fees (always shown, always the last pair) + uint64_t total_fees = G_context.sign_transaction_datas.max_base_fee + + G_context.sign_transaction_datas.max_priority_fee; + if (format_aleo_amount(g_amount_fees, sizeof(g_amount_fees), total_fees) != 0) { + return io_send_sw(SWO_INCORRECT_DATA); + } + + if (G_context.tx.staking.type == TX_STAKING_BOND) { + pairs[pair_index].item = "Validator"; + pairs[pair_index].value = G_context.tx.staking.validator; + pair_index++; + pairs[pair_index].item = "Payout to"; + pairs[pair_index].value = G_context.tx.staking.withdrawal; + pair_index++; + + if (format_aleo_amount(g_amount, sizeof(g_amount), G_context.tx.staking.amount) != 0) { + return io_send_sw(SWO_INCORRECT_DATA); + } + pairs[pair_index].item = "Amount"; + pairs[pair_index].value = g_amount; + pair_index++; + } + else if (G_context.tx.staking.type == TX_STAKING_UNBOND) { + pairs[pair_index].item = "Staker"; + pairs[pair_index].value = G_context.tx.staking.staker; + pair_index++; + + if (format_aleo_amount(g_amount, sizeof(g_amount), G_context.tx.staking.amount) != 0) { + return io_send_sw(SWO_INCORRECT_DATA); + } + pairs[pair_index].item = "Amount"; + pairs[pair_index].value = g_amount; + pair_index++; + } + else { // TX_STAKING_CLAIM — no amount pair + pairs[pair_index].item = "Staker"; + pairs[pair_index].value = G_context.tx.staking.staker; + pair_index++; + } + + // Fees (always last) + pairs[pair_index].item = "Fees"; + pairs[pair_index].value = g_amount_fees; + pair_index++; + + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = pair_index; + pairList.pairs = pairs; + pairList.wrapping = true; + +#ifdef HAVE_SE_TOUCH + nbgl_useCaseReview(TYPE_TRANSACTION, + &pairList, + &ICON_APP_ALEO, + "Review staking transaction?", + review_subtitle, + "Sign staking transaction?", + review_transaction); +#else // !HAVE_SE_TOUCH + nbgl_useCaseReview(TYPE_TRANSACTION, + &pairList, + &ICON_APP_ALEO, + "Review staking transaction?", + review_subtitle, + "Sign transaction", + review_transaction); +#endif // HAVE_SE_TOUCH + + return 0; +} + // Flow used to display a clear-signed transaction int ui_display_transaction(void) { @@ -84,6 +185,10 @@ int ui_display_transaction(void) char amount[MAX_AMOUNT_SIZE] = {0}; const char *review_subtitle = NULL; + if (G_context.tx.type == TX_STAKING) { + return display_review_staking(); + } + if ((G_context.tx.type == TX_ALEO_TRANSFER_PUBLIC) || (G_context.tx.type == TX_TOKEN_TRANSFER_PUBLIC)) { review_subtitle = "Public transfer"; diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00000.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00000.png new file mode 100644 index 00000000..b71c2335 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00000.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00001.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00001.png new file mode 100644 index 00000000..1e438e8e Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00001.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00002.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00002.png new file mode 100644 index 00000000..70003b3c Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00002.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00003.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00003.png new file mode 100644 index 00000000..8955f7b6 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_bond_public/00003.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00000.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00000.png new file mode 100644 index 00000000..e7e6f2da Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00001.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00001.png new file mode 100644 index 00000000..bbd809a4 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00002.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00002.png new file mode 100644 index 00000000..6a6d6c91 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_claim_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00000.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00000.png new file mode 100644 index 00000000..b71c2335 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00000.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00001.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00001.png new file mode 100644 index 00000000..1e438e8e Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00001.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00002.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00002.png new file mode 100644 index 00000000..70003b3c Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00002.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00003.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00003.png new file mode 100644 index 00000000..8955f7b6 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00003.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00004.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00004.png new file mode 100644 index 00000000..cf109394 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_refused/00004.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00000.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00000.png new file mode 100644 index 00000000..b71c2335 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00000.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00001.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00001.png new file mode 100644 index 00000000..1e438e8e Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00001.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00002.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00002.png new file mode 100644 index 00000000..70003b3c Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00002.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00003.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00003.png new file mode 100644 index 00000000..8955f7b6 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_staking_wrong_fee/00003.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00000.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00000.png new file mode 100644 index 00000000..8823c110 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00001.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00001.png new file mode 100644 index 00000000..2ad8a761 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00002.png b/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00002.png new file mode 100644 index 00000000..6a6d6c91 Binary files /dev/null and b/tests/standalone/snapshots/apex_p/test_sign_transaction_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00000.png b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00000.png new file mode 100644 index 00000000..23c703b5 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00000.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00001.png b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00001.png new file mode 100644 index 00000000..68e4681b Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00001.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00002.png b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00002.png new file mode 100644 index 00000000..d47aa834 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00002.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00003.png b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00003.png new file mode 100644 index 00000000..f017b23b Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_bond_public/00003.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00000.png b/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00000.png new file mode 100644 index 00000000..99501072 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00001.png b/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00001.png new file mode 100644 index 00000000..2e02510c Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00002.png b/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00002.png new file mode 100644 index 00000000..8e0fbff1 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_claim_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00000.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00000.png new file mode 100644 index 00000000..23c703b5 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00000.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00001.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00001.png new file mode 100644 index 00000000..68e4681b Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00001.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00002.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00002.png new file mode 100644 index 00000000..d47aa834 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00002.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00003.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00003.png new file mode 100644 index 00000000..f017b23b Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00003.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00004.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00004.png new file mode 100644 index 00000000..315d354c Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00004.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00005.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00005.png new file mode 100644 index 00000000..7de911de Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_refused/00005.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00000.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00000.png new file mode 100644 index 00000000..23c703b5 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00000.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00001.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00001.png new file mode 100644 index 00000000..68e4681b Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00001.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00002.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00002.png new file mode 100644 index 00000000..d47aa834 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00002.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00003.png b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00003.png new file mode 100644 index 00000000..f017b23b Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_staking_wrong_fee/00003.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00000.png b/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00000.png new file mode 100644 index 00000000..fac3d438 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00001.png b/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00001.png new file mode 100644 index 00000000..f6741f07 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00002.png b/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00002.png new file mode 100644 index 00000000..8e0fbff1 Binary files /dev/null and b/tests/standalone/snapshots/flex/test_sign_transaction_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00000.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00000.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00001.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00001.png new file mode 100644 index 00000000..53c1f1f8 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00002.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00002.png new file mode 100644 index 00000000..bd0b33bb Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00003.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00003.png new file mode 100644 index 00000000..17c6ede5 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00003.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00004.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00004.png new file mode 100644 index 00000000..e1a39872 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00004.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00005.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00005.png new file mode 100644 index 00000000..6b016bd8 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00005.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00006.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00006.png new file mode 100644 index 00000000..297a0663 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00006.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00007.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00007.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00007.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00008.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00008.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_bond_public/00008.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00000.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00001.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00001.png new file mode 100644 index 00000000..ac016d21 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00002.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00002.png new file mode 100644 index 00000000..ea3e675e Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00003.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00003.png new file mode 100644 index 00000000..3d03b866 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00003.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00004.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00004.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00004.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00005.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00005.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_claim_unbond_public/00005.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00000.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00000.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00001.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00001.png new file mode 100644 index 00000000..53c1f1f8 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00002.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00002.png new file mode 100644 index 00000000..bd0b33bb Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00002.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00003.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00003.png new file mode 100644 index 00000000..17c6ede5 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00003.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00004.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00004.png new file mode 100644 index 00000000..e1a39872 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00004.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00005.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00005.png new file mode 100644 index 00000000..6b016bd8 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00005.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00006.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00006.png new file mode 100644 index 00000000..297a0663 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00006.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00007.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00007.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00007.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00008.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00008.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00008.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00009.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00009.png new file mode 100644 index 00000000..09a1af10 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00009.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00010.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00010.png new file mode 100644 index 00000000..26c61970 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_refused/00010.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00000.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00000.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00001.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00001.png new file mode 100644 index 00000000..53c1f1f8 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00002.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00002.png new file mode 100644 index 00000000..bd0b33bb Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00002.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00003.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00003.png new file mode 100644 index 00000000..17c6ede5 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00003.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00004.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00004.png new file mode 100644 index 00000000..e1a39872 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00004.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00005.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00005.png new file mode 100644 index 00000000..6b016bd8 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00005.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00006.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00006.png new file mode 100644 index 00000000..297a0663 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00006.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00007.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00007.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00007.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00008.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00008.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_staking_wrong_fee/00008.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00000.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00001.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00001.png new file mode 100644 index 00000000..df75a72f Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00002.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00002.png new file mode 100644 index 00000000..ea3e675e Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00003.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00003.png new file mode 100644 index 00000000..3d03b866 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00003.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00004.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00004.png new file mode 100644 index 00000000..af604a4a Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00004.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00005.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00005.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00005.png differ diff --git a/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00006.png b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00006.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanosp/test_sign_transaction_unbond_public/00006.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00000.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00000.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00001.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00001.png new file mode 100644 index 00000000..53c1f1f8 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00002.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00002.png new file mode 100644 index 00000000..bd0b33bb Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00003.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00003.png new file mode 100644 index 00000000..17c6ede5 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00003.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00004.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00004.png new file mode 100644 index 00000000..e1a39872 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00004.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00005.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00005.png new file mode 100644 index 00000000..6b016bd8 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00005.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00006.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00006.png new file mode 100644 index 00000000..297a0663 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00006.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00007.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00007.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00007.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00008.png b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00008.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_bond_public/00008.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00000.png b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00001.png b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00001.png new file mode 100644 index 00000000..ac016d21 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00002.png b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00002.png new file mode 100644 index 00000000..ea3e675e Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00003.png b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00003.png new file mode 100644 index 00000000..3d03b866 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00003.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00004.png b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00004.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00004.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00005.png b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00005.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_claim_unbond_public/00005.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00000.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00000.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00001.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00001.png new file mode 100644 index 00000000..53c1f1f8 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00002.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00002.png new file mode 100644 index 00000000..bd0b33bb Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00002.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00003.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00003.png new file mode 100644 index 00000000..17c6ede5 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00003.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00004.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00004.png new file mode 100644 index 00000000..e1a39872 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00004.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00005.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00005.png new file mode 100644 index 00000000..6b016bd8 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00005.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00006.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00006.png new file mode 100644 index 00000000..297a0663 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00006.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00007.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00007.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00007.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00008.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00008.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00008.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00009.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00009.png new file mode 100644 index 00000000..09a1af10 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00009.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00010.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00010.png new file mode 100644 index 00000000..26c61970 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_refused/00010.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00000.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00000.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00001.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00001.png new file mode 100644 index 00000000..53c1f1f8 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00002.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00002.png new file mode 100644 index 00000000..bd0b33bb Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00002.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00003.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00003.png new file mode 100644 index 00000000..17c6ede5 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00003.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00004.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00004.png new file mode 100644 index 00000000..e1a39872 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00004.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00005.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00005.png new file mode 100644 index 00000000..6b016bd8 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00005.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00006.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00006.png new file mode 100644 index 00000000..297a0663 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00006.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00007.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00007.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00007.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00008.png b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00008.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_staking_wrong_fee/00008.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00000.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00000.png new file mode 100644 index 00000000..e027ad6c Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00001.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00001.png new file mode 100644 index 00000000..df75a72f Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00002.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00002.png new file mode 100644 index 00000000..ea3e675e Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00003.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00003.png new file mode 100644 index 00000000..3d03b866 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00003.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00004.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00004.png new file mode 100644 index 00000000..af604a4a Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00004.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00005.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00005.png new file mode 100644 index 00000000..1b8dc600 Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00005.png differ diff --git a/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00006.png b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00006.png new file mode 100644 index 00000000..c1d53a3b Binary files /dev/null and b/tests/standalone/snapshots/nanox/test_sign_transaction_unbond_public/00006.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00000.png b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00000.png new file mode 100644 index 00000000..9df0c655 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00000.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00001.png b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00001.png new file mode 100644 index 00000000..7470d214 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00001.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00002.png b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00002.png new file mode 100644 index 00000000..e43fd06d Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00002.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00003.png b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00003.png new file mode 100644 index 00000000..a9dc0402 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_bond_public/00003.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00000.png b/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00000.png new file mode 100644 index 00000000..0c9b9314 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00001.png b/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00001.png new file mode 100644 index 00000000..9bc72adf Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00002.png b/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00002.png new file mode 100644 index 00000000..0b39cc81 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_claim_unbond_public/00002.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00000.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00000.png new file mode 100644 index 00000000..9df0c655 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00000.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00001.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00001.png new file mode 100644 index 00000000..7470d214 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00001.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00002.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00002.png new file mode 100644 index 00000000..e43fd06d Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00002.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00003.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00003.png new file mode 100644 index 00000000..a9dc0402 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00003.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00004.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00004.png new file mode 100644 index 00000000..abc9677f Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_refused/00004.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00000.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00000.png new file mode 100644 index 00000000..9df0c655 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00000.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00001.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00001.png new file mode 100644 index 00000000..7470d214 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00001.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00002.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00002.png new file mode 100644 index 00000000..e43fd06d Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00002.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00003.png b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00003.png new file mode 100644 index 00000000..a9dc0402 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_staking_wrong_fee/00003.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00000.png b/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00000.png new file mode 100644 index 00000000..7f477f5d Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00000.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00001.png b/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00001.png new file mode 100644 index 00000000..5ec8fce9 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00001.png differ diff --git a/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00002.png b/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00002.png new file mode 100644 index 00000000..0b39cc81 Binary files /dev/null and b/tests/standalone/snapshots/stax/test_sign_transaction_unbond_public/00002.png differ diff --git a/tests/standalone/test_sign_transaction.py b/tests/standalone/test_sign_transaction.py index accdac76..5c4338a4 100644 --- a/tests/standalone/test_sign_transaction.py +++ b/tests/standalone/test_sign_transaction.py @@ -61,6 +61,47 @@ def forge_public_transfer( return data +def forge_bond_public(max_base_fee: int, max_priority_fee: int, validator: str, + withdrawal: str, amount: int, program_checksum: str = '') -> dict: + data = {'type': 'intent', + 'max_base_fee': max_base_fee, 'max_priority_fee': max_priority_fee, + 'fee_program_id': 'credits.aleo', 'fee_function_name': 'fee_public'} + data['request'] = {'network_id': 'mainnet', 'program_id': 'credits.aleo', + 'function_name': 'bond_public'} + data['request']['inputs'] = [{'type': 'address.public', 'value': validator}, + {'type': 'address.public', 'value': withdrawal}, + {'type': 'u64.public', 'value': amount}] + data['request']['nested_call_count'] = 0 + data['request']['program_checksum'] = program_checksum + return data + + +def forge_unbond_public(max_base_fee: int, max_priority_fee: int, staker: str, + amount: int, program_checksum: str = '') -> dict: + data = {'type': 'intent', + 'max_base_fee': max_base_fee, 'max_priority_fee': max_priority_fee, + 'fee_program_id': 'credits.aleo', 'fee_function_name': 'fee_public'} + data['request'] = {'network_id': 'mainnet', 'program_id': 'credits.aleo', + 'function_name': 'unbond_public'} + data['request']['inputs'] = [{'type': 'address.public', 'value': staker}, + {'type': 'u64.public', 'value': amount}] + data['request']['nested_call_count'] = 0 + data['request']['program_checksum'] = program_checksum + return data + + +def forge_claim_unbond_public(max_base_fee: int, max_priority_fee: int, staker: str, + program_checksum: str = '') -> dict: + data = {'type': 'intent', + 'max_base_fee': max_base_fee, 'max_priority_fee': max_priority_fee, + 'fee_program_id': 'credits.aleo', 'fee_function_name': 'fee_public'} + data['request'] = {'network_id': 'mainnet', 'program_id': 'credits.aleo', + 'function_name': 'claim_unbond_public'} + data['request']['inputs'] = [{'type': 'address.public', 'value': staker}] + data['request']['nested_call_count'] = 0 + data['request']['program_checksum'] = program_checksum + return data + def forge_private_transfer( max_base_fee: int, max_priority_fee: int, @@ -1906,3 +1947,128 @@ def test_sign_transaction_token_arc22_transfer_public_to_private( "gammas_count": 0, } assert check_response(unpacked, expected) + + +def test_sign_transaction_bond_public(backend: BackendInterface, scenario_navigator: NavigateWithScenario) -> None: + client = CommandSender(backend) + tx_datas = forge_bond_public( + 500, 100, + "aleo1sfydt6z6cnqjx3hcgk9ajw03ecj6uqlfcm9u3p3gdhckzcc2w5xqv3v3pe", # validator + "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px", # withdrawal + 10000000000) # 10,000 ALEO + tx_datas['path'] = "m/44'/683'/0'/0'" + with client.sign_transaction(tx_datas=tx_datas): + scenario_navigator.review_approve_with_spinner("Calculating fees") + response = client.get_async_response().data + unpacked = unpack_sign_transaction_response(response) + expected = {'structure_type': 42, + 'version': 1, + 'signature': {'pk_sig': '1d4c4b28dd6ce05ab520f00b71c081d480684c746a7d8f3b0a3a68d410ce840e', + 'pr_sig': '3a8a3cfee21ce108285cca4cc50abb5ac9044acf26959ddb7722cbb968bdc310'}, + 'tvk': '4550d3f0247ac00ea42b431643f2e20128163c3cf9e5bdd4148c98d3039a030d', + 'tpk': '91954cc04716f1be8f53f78efb7f4e50fa9fb87a10006d56c75998396df5b702', + 'gammas_count': 0 + } + assert check_response(unpacked, expected) + + +def test_sign_transaction_unbond_public(backend: BackendInterface, scenario_navigator: NavigateWithScenario) -> None: + client = CommandSender(backend) + tx_datas = forge_unbond_public( + 500, 100, + "aleo1sfydt6z6cnqjx3hcgk9ajw03ecj6uqlfcm9u3p3gdhckzcc2w5xqv3v3pe", # staker + 5000000000) # 5,000 ALEO + tx_datas['path'] = "m/44'/683'/0'/0'" + with client.sign_transaction(tx_datas=tx_datas): + scenario_navigator.review_approve_with_spinner("Calculating fees") + response = client.get_async_response().data + unpacked = unpack_sign_transaction_response(response) + expected = {'structure_type': 42, + 'version': 1, + 'signature': {'pk_sig': '1d4c4b28dd6ce05ab520f00b71c081d480684c746a7d8f3b0a3a68d410ce840e', + 'pr_sig': '3a8a3cfee21ce108285cca4cc50abb5ac9044acf26959ddb7722cbb968bdc310'}, + 'tvk': '002bc276c9bc0f8fef614b7b3a906197fe5f41db9b56e07276e2ecf5b059510b', + 'tpk': '4eccd2d0262845cfcfc29944d1daa0ae82fa2dfea74dbb3980770f04face530e', + 'gammas_count': 0 + } + assert check_response(unpacked, expected) + + +def test_sign_transaction_claim_unbond_public(backend: BackendInterface, scenario_navigator: NavigateWithScenario) -> None: + client = CommandSender(backend) + tx_datas = forge_claim_unbond_public( + 500, 100, + "aleo1sfydt6z6cnqjx3hcgk9ajw03ecj6uqlfcm9u3p3gdhckzcc2w5xqv3v3pe") # staker + tx_datas['path'] = "m/44'/683'/0'/0'" + with client.sign_transaction(tx_datas=tx_datas): + scenario_navigator.review_approve_with_spinner("Calculating fees") + response = client.get_async_response().data + unpacked = unpack_sign_transaction_response(response) + expected = {'structure_type': 42, + 'version': 1, + 'signature': {'pk_sig': '1d4c4b28dd6ce05ab520f00b71c081d480684c746a7d8f3b0a3a68d410ce840e', + 'pr_sig': '3a8a3cfee21ce108285cca4cc50abb5ac9044acf26959ddb7722cbb968bdc310'}, + 'tvk': '3f0975c11a2f22f31f1b1e66960994c177d3ac4ef655df2bb12e0c25b88fcf0b', + 'tpk': '2d2e11080282f0ef8248be7ab4ccf773cb934405df070ee897dc65f6f3e16a03', + 'gammas_count': 0 + } + assert check_response(unpacked, expected) + + +def test_sign_transaction_staking_refused(backend: BackendInterface, scenario_navigator: NavigateWithScenario) -> None: + client = CommandSender(backend) + tx_datas = forge_bond_public( + 500, 100, + "aleo1sfydt6z6cnqjx3hcgk9ajw03ecj6uqlfcm9u3p3gdhckzcc2w5xqv3v3pe", # validator + "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px", # withdrawal + 10000000000) # 10,000 ALEO + tx_datas['path'] = "m/44'/683'/0'/0'" + + with pytest.raises(ExceptionRAPDU) as e: + with client.sign_transaction(tx_datas=tx_datas): + scenario_navigator.review_reject() + + assert e.value.status == StatusWords.SWO_PERMISSION_DENIED + assert len(e.value.data) == 0 + + if scenario_navigator.device.is_nano: + instruction = NavInsID.BOTH_CLICK + else: + instruction = NavInsID.USE_CASE_REVIEW_TAP + scenario_navigator.navigator.navigate_until_text(navigate_instruction=instruction, + validation_instructions=None, + text="Transaction rejected", + timeout=3, + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=True) + + +def test_sign_transaction_staking_wrong_fee(backend: BackendInterface, scenario_navigator: NavigateWithScenario) -> None: + client = CommandSender(backend) + tx_datas = forge_bond_public( + 500, 100, + "aleo1sfydt6z6cnqjx3hcgk9ajw03ecj6uqlfcm9u3p3gdhckzcc2w5xqv3v3pe", # validator + "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px", # withdrawal + 10000000000) # 10,000 ALEO + tx_datas['path'] = "m/44'/683'/0'/0'" + with client.sign_transaction(tx_datas=tx_datas): + scenario_navigator.review_approve_with_spinner("Calculating fees") + + response = client.get_async_response().data + unpacked = unpack_sign_transaction_response(response) + expected = {'structure_type': 42, + 'version': 1, + 'signature': {'pk_sig': '1d4c4b28dd6ce05ab520f00b71c081d480684c746a7d8f3b0a3a68d410ce840e', + 'pr_sig': '3a8a3cfee21ce108285cca4cc50abb5ac9044acf26959ddb7722cbb968bdc310'}, + 'tvk': '4550d3f0247ac00ea42b431643f2e20128163c3cf9e5bdd4148c98d3039a030d', + 'tpk': '91954cc04716f1be8f53f78efb7f4e50fa9fb87a10006d56c75998396df5b702', + 'gammas_count': 0 + } + assert check_response(unpacked, expected) + + tx_datas = forge_public_fee(5000, 1000, "7266375125414209082394925781071362722506946030314916664133746682226945366259field") + + with pytest.raises(ExceptionRAPDU) as e: + with client.sign_transaction(tx_datas=tx_datas): + pass + assert e.value.status == StatusWords.SWO_INCORRECT_DATA diff --git a/tools/python/program_function.json b/tools/python/program_function.json index 9363a87c..1753314e 100644 --- a/tools/python/program_function.json +++ b/tools/python/program_function.json @@ -23,7 +23,16 @@ "input_count" : 2}, {"function" : "join", "tx_type" : "TX_JOIN", - "input_count" : 2} + "input_count" : 2}, + {"function" : "bond_public", + "tx_type" : "TX_STAKING", + "input_count" : 3}, + {"function" : "unbond_public", + "tx_type" : "TX_STAKING", + "input_count" : 2}, + {"function" : "claim_unbond_public", + "tx_type" : "TX_STAKING", + "input_count" : 1} ], "ldg_p_28.aleo" : [ {"function" : "transfer_private_2", diff --git a/unit-tests/test_bhp_1024.c b/unit-tests/test_bhp_1024.c index 09680e4e..1b830bb8 100644 --- a/unit-tests/test_bhp_1024.c +++ b/unit-tests/test_bhp_1024.c @@ -200,6 +200,46 @@ static bhp_test_t bhp_tests[] = { {.big.u64 = {0x3ad6cd9ea53fbfce, 0xdf3d3dbe8a6c7f3b, 0xb077de61a52f2ee8, 0x0a2983140a27e484}}}, }, + /* staking functions — golden values from db_program_function.c's credits_aleo table */ + { + .status = 0, + .request = {.network_id = 0, + .program_id = "credits.aleo", + .program_id_length = 12, + .function_name = "bond_public", + .function_name_length = 11}, + .hash + = {{.big.u64 + = {0xfad1870949c8aa5f, 0xb94139693a1a9ede, 0x13826b9d3dda98ed, 0x11692029f1d694e3}}, + {.big.u64 + = {0x11e14f163d3f2b7c, 0xc591f619d35fb0ab, 0x3456c789125b6f67, 0x0eec83be57f64f40}}}, + }, + { + .status = 0, + .request = {.network_id = 0, + .program_id = "credits.aleo", + .program_id_length = 12, + .function_name = "unbond_public", + .function_name_length = 13}, + .hash + = {{.big.u64 + = {0x7023ecbf86089ad7, 0x1d8626b632ad9001, 0x9f1706e883708361, 0x029c23c1fc2b9465}}, + {.big.u64 + = {0x75ca6051e895980f, 0x86110aa6b233d58e, 0x53106280baec89af, 0x0628c9c0bfeaeb79}}}, + }, + { + .status = 0, + .request = {.network_id = 0, + .program_id = "credits.aleo", + .program_id_length = 12, + .function_name = "claim_unbond_public", + .function_name_length = 19}, + .hash + = {{.big.u64 + = {0x44e8eea54a97db6b, 0x137b370eeb14174b, 0xb14498709cf52fb5, 0x10df36004e953eb8}}, + {.big.u64 + = {0xe506d14510bc7c88, 0xb5566ac3133fe094, 0x8c7852dcca7e24e1, 0x0bce73be56cbba46}}}, + }, // failure { diff --git a/unit-tests/test_db.c b/unit-tests/test_db.c index 43f54a66..0db924ad 100644 --- a/unit-tests/test_db.c +++ b/unit-tests/test_db.c @@ -38,6 +38,36 @@ static void test_db(void **state) program_id, program_length, function_name, function_name_length, &function_parameters); assert_int_equal(status, -1); + strncpy(program_id, "credits.aleo", sizeof(program_id)); + strncpy(function_name, "bond_public", sizeof(function_name)); + program_length = strlen(program_id); + function_name_length = strlen(function_name); + status = db_get_function_parameters( + program_id, program_length, function_name, function_name_length, &function_parameters); + assert_int_equal(status, 0); + assert_int_equal(function_parameters->tx_type, TX_STAKING); + assert_int_equal(function_parameters->input_count, 3); + + strncpy(program_id, "credits.aleo", sizeof(program_id)); + strncpy(function_name, "unbond_public", sizeof(function_name)); + program_length = strlen(program_id); + function_name_length = strlen(function_name); + status = db_get_function_parameters( + program_id, program_length, function_name, function_name_length, &function_parameters); + assert_int_equal(status, 0); + assert_int_equal(function_parameters->tx_type, TX_STAKING); + assert_int_equal(function_parameters->input_count, 2); + + strncpy(program_id, "credits.aleo", sizeof(program_id)); + strncpy(function_name, "claim_unbond_public", sizeof(function_name)); + program_length = strlen(program_id); + function_name_length = strlen(function_name); + status = db_get_function_parameters( + program_id, program_length, function_name, function_name_length, &function_parameters); + assert_int_equal(status, 0); + assert_int_equal(function_parameters->tx_type, TX_STAKING); + assert_int_equal(function_parameters->input_count, 1); + strncpy(program_id, "usad_stablecoin.aleo", sizeof(program_id)); strncpy(function_name, "transfer_public", sizeof(function_name)); program_length = strlen(program_id); diff --git a/unit-tests/test_transaction.c b/unit-tests/test_transaction.c index 9c34a608..878b2a2f 100644 --- a/unit-tests/test_transaction.c +++ b/unit-tests/test_transaction.c @@ -12,55 +12,55 @@ global_ctx_t G_context; -static void test_tx_extract(void **state) +static void test_tx_extract(void** state) { - (void) state; + (void)state; memset(&G_context, 0, sizeof(G_context)); // tx_extract_intent uint8_t payload[161] = "\x01\x01\x28\x02\x01\x01\x81\xB0\x04\x00\x00\x01\xF4\x81\xB1\x04\x00\x00\x00\x64\x81\xB2" - "\x0A\x66\x65\x65\x5F\x70\x75\x62\x6C\x69\x63\x81\xB3\x0C\x63\x72\x65\x64\x69\x74\x73\x2E" - "\x61\x6C\x65\x6F\x81\xB4\x6E\x01\x01\x29\x02\x01\x01\x81\xC3\x02\x00\x00\x81\xB5\x0C\x63" - "\x72\x65\x64\x69\x74\x73\x2E\x61\x6C\x65\x6F\x81\xB6\x0F\x74\x72\x61\x6E\x73\x66\x65\x72" - "\x5F\x70\x75\x62\x6C\x69\x63\x81\xB7\x01\x02\x81\xB9\x03\x01\x00\x00\x81\xB8\x20\x82\x48" - "\xD5\xE8\x5A\xC4\xC1\x23\x46\xF8\x45\x8B\xD9\x39\xF1\xCE\x25\xAE\x03\xE9\xC6\xCB\xC8\x86" - "\x28\x6D\xF1\x61\x63\x0A\x75\x0C\x81\xB9\x03\x01\x00\x0C\x81\xB8\x08\xE8\x03\x00\x00\x00" - "\x00\x00\x00\x81\xBA\x01\x00"; + "\x0A\x66\x65\x65\x5F\x70\x75\x62\x6C\x69\x63\x81\xB3\x0C\x63\x72\x65\x64\x69\x74\x73\x2E" + "\x61\x6C\x65\x6F\x81\xB4\x6E\x01\x01\x29\x02\x01\x01\x81\xC3\x02\x00\x00\x81\xB5\x0C\x63" + "\x72\x65\x64\x69\x74\x73\x2E\x61\x6C\x65\x6F\x81\xB6\x0F\x74\x72\x61\x6E\x73\x66\x65\x72" + "\x5F\x70\x75\x62\x6C\x69\x63\x81\xB7\x01\x02\x81\xB9\x03\x01\x00\x00\x81\xB8\x20\x82\x48" + "\xD5\xE8\x5A\xC4\xC1\x23\x46\xF8\x45\x8B\xD9\x39\xF1\xCE\x25\xAE\x03\xE9\xC6\xCB\xC8\x86" + "\x28\x6D\xF1\x61\x63\x0A\x75\x0C\x81\xB9\x03\x01\x00\x0C\x81\xB8\x08\xE8\x03\x00\x00\x00" + "\x00\x00\x00\x81\xBA\x01\x00"; buffer_t buffer; - buffer.ptr = payload; - buffer.size = sizeof(payload); + buffer.ptr = payload; + buffer.size = sizeof(payload); buffer.offset = 0; assert_int_equal(tx_extract_intent(&buffer), 0); uint8_t fee_function_name[73] = "\x81\xb2\x46\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" - "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" - "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" - "\x63\x72\x65\x64\x69\x74\x73"; - buffer.ptr = fee_function_name; - buffer.size = sizeof(fee_function_name); + "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" + "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" + "\x63\x72\x65\x64\x69\x74\x73"; + buffer.ptr = fee_function_name; + buffer.size = sizeof(fee_function_name); buffer.offset = 0; assert_int_equal(tx_extract_intent(&buffer), -1); uint8_t fee_program_id[73] = "\x81\xb3\x46\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" - "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" - "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" - "\x63\x72\x65\x64\x69\x74\x73"; - buffer.ptr = fee_program_id; - buffer.size = sizeof(fee_program_id); + "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" + "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" + "\x63\x72\x65\x64\x69\x74\x73"; + buffer.ptr = fee_program_id; + buffer.size = sizeof(fee_program_id); buffer.offset = 0; assert_int_equal(tx_extract_intent(&buffer), -1); // tx_extract_prepared_request uint8_t program_id[73] = "\x81\xb5\x46\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" - "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" - "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" - "\x63\x72\x65\x64\x69\x74\x73"; - buffer.ptr = program_id; - buffer.size = sizeof(program_id); + "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" + "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" + "\x63\x72\x65\x64\x69\x74\x73"; + buffer.ptr = program_id; + buffer.size = sizeof(program_id); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -68,11 +68,11 @@ static void test_tx_extract(void **state) uint8_t function_name[73] = "\x81\xb6\x46\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" - "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" - "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" - "\x63\x72\x65\x64\x69\x74\x73"; - buffer.ptr = function_name; - buffer.size = sizeof(function_name); + "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" + "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" + "\x63\x72\x65\x64\x69\x74\x73"; + buffer.ptr = function_name; + buffer.size = sizeof(function_name); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -80,14 +80,14 @@ static void test_tx_extract(void **state) uint8_t input_value[144] = "\x81\xb8\x81\x8c\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64" - "\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" - "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" - "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" - "\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63" - "\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72" - "\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73"; - buffer.ptr = input_value; - buffer.size = sizeof(input_value); + "\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" + "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" + "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" + "\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63" + "\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72" + "\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73"; + buffer.ptr = input_value; + buffer.size = sizeof(input_value); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -95,11 +95,11 @@ static void test_tx_extract(void **state) uint8_t input_values[78] = "\x81\xb8\x01\x01\x81\xb8\x01\x02\x81\xb8\x01\x03\x81\xb8\x01\x04\x81\xb8\x01\x05\x81\xb8" - "\x01\x06\x81\xb8\x01\x07\x81\xb8\x01\x08\x81\xb8\x01\x09\x81\xb8\x01\x0a\x81\xb8\x01\x0b" - "\x81\xb8\x01\x0c\x81\xb8\x01\x0d\x81\xb8\x01\x0e\x81\xb8\x01\x0f\x81\xb8\x01\x10\x81\xb8" - "\x01\x11"; - buffer.ptr = input_values; - buffer.size = sizeof(input_values); + "\x01\x06\x81\xb8\x01\x07\x81\xb8\x01\x08\x81\xb8\x01\x09\x81\xb8\x01\x0a\x81\xb8\x01\x0b" + "\x81\xb8\x01\x0c\x81\xb8\x01\x0d\x81\xb8\x01\x0e\x81\xb8\x01\x0f\x81\xb8\x01\x10\x81\xb8" + "\x01\x11"; + buffer.ptr = input_values; + buffer.size = sizeof(input_values); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -107,14 +107,14 @@ static void test_tx_extract(void **state) uint8_t input_type[144] = "\x81\xb9\x81\x8c\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64" - "\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" - "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" - "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" - "\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63" - "\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72" - "\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73"; - buffer.ptr = input_type; - buffer.size = sizeof(input_type); + "\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69" + "\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74" + "\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73" + "\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63" + "\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73\x63\x72" + "\x65\x64\x69\x74\x73\x63\x72\x65\x64\x69\x74\x73"; + buffer.ptr = input_type; + buffer.size = sizeof(input_type); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -122,11 +122,11 @@ static void test_tx_extract(void **state) uint8_t input_types[78] = "\x81\xb9\x01\x01\x81\xb9\x01\x02\x81\xb9\x01\x03\x81\xb9\x01\x04\x81\xb9\x01\x05\x81\xb9" - "\x01\x06\x81\xb9\x01\x07\x81\xb9\x01\x08\x81\xb9\x01\x09\x81\xb9\x01\x0a\x81\xb9\x01\x0b" - "\x81\xb9\x01\x0c\x81\xb9\x01\x0d\x81\xb9\x01\x0e\x81\xb9\x01\x0f\x81\xb9\x01\x10\x81\xb9" - "\x01\x11"; - buffer.ptr = input_types; - buffer.size = sizeof(input_types); + "\x01\x06\x81\xb9\x01\x07\x81\xb9\x01\x08\x81\xb9\x01\x09\x81\xb9\x01\x0a\x81\xb9\x01\x0b" + "\x81\xb9\x01\x0c\x81\xb9\x01\x0d\x81\xb9\x01\x0e\x81\xb9\x01\x0f\x81\xb9\x01\x10\x81\xb9" + "\x01\x11"; + buffer.ptr = input_types; + buffer.size = sizeof(input_types); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -134,9 +134,9 @@ static void test_tx_extract(void **state) uint8_t program_checksum[35] = "\x81\xc4\x20\x01\x81\xb9\x01\x02\x81\xb9\x01\x03\x81\xb9\x01\x04\x81\xb9\x01\x05\x81\xb9" - "\x01\x06\x81\xb9\x01\x07\x81\xb9\x01\x08\x81\xb9\x01"; - buffer.ptr = program_checksum; - buffer.size = sizeof(program_checksum); + "\x01\x06\x81\xb9\x01\x07\x81\xb9\x01\x08\x81\xb9\x01"; + buffer.ptr = program_checksum; + buffer.size = sizeof(program_checksum); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), @@ -144,46 +144,52 @@ static void test_tx_extract(void **state) uint8_t program_checksum_2[34] = "\x81\xc4\x1f\x01\x81\xb9\x01\x02\x81\xb9\x01\x03\x81\xb9\x01\x04\x81\xb9\x01\x05\x81\xb9" - "\x01\x06\x81\xb9\x01\x07\x81\xb9\x01\x08\x81\xb9"; - buffer.ptr = program_checksum_2; - buffer.size = sizeof(program_checksum_2); + "\x01\x06\x81\xb9\x01\x07\x81\xb9\x01\x08\x81\xb9"; + buffer.ptr = program_checksum_2; + buffer.size = sizeof(program_checksum_2); buffer.offset = 0; assert_int_equal( tx_extract_prepared_request(&buffer, &G_context.sign_transaction_datas.prepared_request), -1); } -static void test_tx_parse(void **state) +static void test_tx_parse(void** state) { - (void) state; + (void)state; memset(&G_context, 0, sizeof(G_context)); tx_t tx; sign_transaction_datas_t datas_public = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 10, - .fee_function_name = "fee_public", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", - .prepared_request = { - .program_id_length = 12, - .program_id = "credits.aleo", - .function_name_length = 15, - .function_name = "transfer_public", - .inputs_count = 2, - .inputs - = {{.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x00"}, - {.value_length = 8, - .value = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0c"}}, - } + .fee_function_name = "fee_public", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", + .prepared_request = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 15, + .function_name = "transfer_public", + .inputs_count = 2, + .inputs + = { + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x00" + }, + { + .value_length = 8, + .value = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0c" + } + }, + } }; datas_public.prepared_request.inputs_count = 1; @@ -195,9 +201,9 @@ static void test_tx_parse(void **state) assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.inputs[1].type_length = 3; - uint8_t type_1[3] = "\x01\x00\x0c"; - uint8_t type_2[3] = "\x02\x00\x0c"; - uint8_t type_3[3] = "\x01\x01\x0c"; + uint8_t type_1[3] = "\x01\x00\x0c"; + uint8_t type_2[3] = "\x02\x00\x0c"; + uint8_t type_3[3] = "\x01\x01\x0c"; datas_public.prepared_request.inputs[1].type = type_2; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.inputs[1].type = type_3; @@ -207,81 +213,91 @@ static void test_tx_parse(void **state) datas_public.prepared_request.inputs[0].type_length = 2; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.inputs[0].type_length = 3; - uint8_t type_11[3] = "\x01\x00\x00"; - uint8_t type_12[3] = "\x02\x00\x00"; - uint8_t type_13[3] = "\x01\x01\x00"; - datas_public.prepared_request.inputs[0].type = type_12; + uint8_t type_11[3] = "\x01\x00\x00"; + uint8_t type_12[3] = "\x02\x00\x00"; + uint8_t type_13[3] = "\x01\x01\x00"; + datas_public.prepared_request.inputs[0].type = type_12; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.inputs[0].type = type_13; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.inputs[0].type = type_11; - char program_id[12] = "credits.aleo"; + char program_id[12] = "credits.aleo"; datas_public.prepared_request.program_id = NULL; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.program_id = program_id; - char function_name[15] = "transfer_public"; + char function_name[15] = "transfer_public"; datas_public.prepared_request.function_name = NULL; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.function_name = function_name; - char program_id_2[12] = "credots.aleo"; + char program_id_2[12] = "credots.aleo"; datas_public.prepared_request.program_id = program_id_2; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.program_id = program_id; - char function_name_2[15] = "tronsfer_public"; + char function_name_2[15] = "tronsfer_public"; datas_public.prepared_request.function_name = function_name_2; assert_int_equal(tx_parse(&datas_public, &tx), -1); datas_public.prepared_request.function_name = function_name; assert_int_equal(tx_parse(&datas_public, &tx), 0); - char function_name_3[26] = "transfer_public_to_private"; + char function_name_3[26] = "transfer_public_to_private"; datas_public.prepared_request.function_name_length = sizeof(function_name_3); - datas_public.prepared_request.function_name = function_name_3; - datas_public.prepared_request.inputs[0].type = type_12; + datas_public.prepared_request.function_name = function_name_3; + datas_public.prepared_request.inputs[0].type = type_12; assert_int_equal(tx_parse(&datas_public, &tx), 0); datas_public.prepared_request.inputs[0].type = type_11; assert_int_equal(tx_parse(&datas_public, &tx), -1); const uint8_t hash_record_c[96] = "\xf4\x69\x19\x61\x50\x7b\x8f\x32\x92\xaf\x47\xac\x64\xdf\x59\xf7" - "\xc4\x39\xf6\xb2\x48\xa9\x55\x10\xfa\x95\xcc\x96\x25\xe7\xfd\x07" - "\x2a\xe1\x18\xb5\x2d\x46\xd6\x0b\x96\x63\x06\x72\x73\x3d\x25\x2c" - "\xa9\x3f\xbb\x8d\x56\xd5\x26\x1c\x0c\x4c\xbb\x8c\xf2\x92\x5d\x05" - "\xd9\x75\x64\x3e\x43\x24\x5c\x7a\xf2\x8d\xb2\xa8\x5b\x54\x59\xb4" - "\xb7\x7b\x38\x2a\x0c\x74\x33\x0c\x1d\x53\x7a\xa9\x22\xe1\x7c\x00"; - uint8_t hash_record[96]; + "\xc4\x39\xf6\xb2\x48\xa9\x55\x10\xfa\x95\xcc\x96\x25\xe7\xfd\x07" + "\x2a\xe1\x18\xb5\x2d\x46\xd6\x0b\x96\x63\x06\x72\x73\x3d\x25\x2c" + "\xa9\x3f\xbb\x8d\x56\xd5\x26\x1c\x0c\x4c\xbb\x8c\xf2\x92\x5d\x05" + "\xd9\x75\x64\x3e\x43\x24\x5c\x7a\xf2\x8d\xb2\xa8\x5b\x54\x59\xb4" + "\xb7\x7b\x38\x2a\x0c\x74\x33\x0c\x1d\x53\x7a\xa9\x22\xe1\x7c\x00"; + uint8_t hash_record[96]; sign_transaction_datas_t datas_private = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 11, - .fee_function_name = "fee_private", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", + .fee_function_name = "fee_private", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", .prepared_request - = {.program_id_length = 12, - .program_id = "credits.aleo", - .function_name_length = 16, - .function_name = "transfer_private", - .inputs_count = 3, - .inputs - = {{.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x03\x07\x63\x72\x65\x64\x69\x74\x73"}, - {.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x00"}, - {.value_length = 8, - .value = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x0c"}}} + = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 16, + .function_name = "transfer_private", + .inputs_count = 3, + .inputs + = { + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x03\x07\x63\x72\x65\x64\x69\x74\x73" + }, + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x00" + }, + { + .value_length = 8, + .value = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x0c" + } + } + } }; memcpy(hash_record, hash_record_c, 96); @@ -291,117 +307,151 @@ static void test_tx_parse(void **state) assert_int_equal(tx_parse(&datas_private, &tx), -1); datas_private.prepared_request.inputs[2].type = type_2; - char function_name_4[26] = "transfer_private_to_public"; + char function_name_4[26] = "transfer_private_to_public"; datas_private.prepared_request.function_name_length = sizeof(function_name_4); - datas_private.prepared_request.function_name = function_name_4; - datas_private.prepared_request.inputs[1].type = type_11; - datas_private.prepared_request.inputs[2].type = type_1; + datas_private.prepared_request.function_name = function_name_4; + datas_private.prepared_request.inputs[1].type = type_11; + datas_private.prepared_request.inputs[2].type = type_1; assert_int_equal(tx_parse(&datas_private, &tx), 0); - char function_name_5[11] = "fee_private"; + char function_name_5[11] = "fee_private"; datas_private.prepared_request.function_name_length = sizeof(function_name_5); - datas_private.prepared_request.function_name = function_name_5; + datas_private.prepared_request.function_name = function_name_5; sign_transaction_datas_t datas_private_2 = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 11, - .fee_function_name = "fee_private", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", + .fee_function_name = "fee_private", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", .prepared_request - = {.program_id_length = 12, - .program_id = "credits.aleo", - .function_name_length = 11, - .function_name = "fee_private", - .inputs_count = 4, - .inputs - = {{.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x03\x07\x63\x72\x65\x64\x69\x74\x73"}, - {.value_length = 8, - .value = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0c"}, - {.value_length = 8, - .value = (uint8_t *) "\x64\x00\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0c"}, - {.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x02"}}} + = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 11, + .function_name = "fee_private", + .inputs_count = 4, + .inputs + = { + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x03\x07\x63\x72\x65\x64\x69\x74\x73" + }, + { + .value_length = 8, + .value = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0c" + }, + { + .value_length = 8, + .value = (uint8_t*)"\x64\x00\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0c" + }, + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x02" + } + } + } }; assert_int_equal(tx_parse(&datas_private_2, &tx), 0); sign_transaction_datas_t datas_private_3 = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 10, - .fee_function_name = "fee_public", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", + .fee_function_name = "fee_public", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", .prepared_request - = {.program_id_length = 12, - .program_id = "credits.aleo", - .function_name_length = 10, - .function_name = "fee_public", - .inputs_count = 3, - .inputs - = {{.value_length = 8, - .value = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0c"}, - {.value_length = 8, - .value = (uint8_t *) "\x64\x00\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0c"}, - {.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x02"}}} + = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 10, + .function_name = "fee_public", + .inputs_count = 3, + .inputs + = { + { + .value_length = 8, + .value = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0c" + }, + { + .value_length = 8, + .value = (uint8_t*)"\x64\x00\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0c" + }, + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x02" + } + } + } }; assert_int_equal(tx_parse(&datas_private_3, &tx), 0); sign_transaction_datas_t datas_batch_private = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 11, - .fee_function_name = "fee_private", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", + .fee_function_name = "fee_private", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", .prepared_request - = {.program_id_length = 13, - .program_id = "ldg_p_28.aleo", - .function_name_length = 18, - .function_name = "transfer_private_2", - .inputs_count = 4, - .inputs - = {{.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x03\x07\x63\x72\x65\x64\x69\x74\x73"}, - {.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x03\x07\x63\x72\x65\x64\x69\x74\x73"}, - {.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x00"}, - {.value_length = 8, - .value = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x0c"}}} + = { + .program_id_length = 13, + .program_id = "ldg_p_28.aleo", + .function_name_length = 18, + .function_name = "transfer_private_2", + .inputs_count = 4, + .inputs + = { + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x03\x07\x63\x72\x65\x64\x69\x74\x73" + }, + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x03\x07\x63\x72\x65\x64\x69\x74\x73" + }, + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x00" + }, + { + .value_length = 8, + .value = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x0c" + } + } + } }; assert_int_equal(tx_parse(&datas_batch_private, &tx), 0); @@ -410,29 +460,39 @@ static void test_tx_parse(void **state) assert_int_equal(tx_parse(&datas_batch_private, &tx), -1); sign_transaction_datas_t datas_batch_private_to_public = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 11, - .fee_function_name = "fee_private", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", - .prepared_request = {.program_id_length = 15, - .program_id = "ldg_p2p_28.aleo", - .function_name_length = 28, - .function_name = "transfer_private_to_public_2", - .inputs_count = 3, - .inputs = {{.value_length = 96, - .value = hash_record, - .type_length = 1, - .type = (uint8_t *) "\x04"}, - {.value_length = 96, - .value = hash_record, - .type_length = 1, - .type = (uint8_t *) "\x04"}, - {.value_length = 8, - .value = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0c"}}} + .fee_function_name = "fee_private", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", + .prepared_request = { + .program_id_length = 15, + .program_id = "ldg_p2p_28.aleo", + .function_name_length = 28, + .function_name = "transfer_private_to_public_2", + .inputs_count = 3, + .inputs = { + { + .value_length = 96, + .value = hash_record, + .type_length = 1, + .type = (uint8_t*)"\x04" + }, + { + .value_length = 96, + .value = hash_record, + .type_length = 1, + .type = (uint8_t*)"\x04" + }, + { + .value_length = 8, + .value = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0c" + } + } + } }; assert_int_equal(tx_parse(&datas_batch_private_to_public, &tx), 0); @@ -441,38 +501,44 @@ static void test_tx_parse(void **state) assert_int_equal(tx_parse(&datas_batch_private_to_public, &tx), -1); } -static void test_tx_token_parse(void **state) +static void test_tx_token_parse(void** state) { - (void) state; + (void)state; memset(&G_context, 0, sizeof(G_context)); tx_t tx; sign_transaction_datas_t datas_token_public = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 10, - .fee_function_name = "fee_public", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", - .prepared_request = { - .program_id_length = 20, - .program_id = "usad_stablecoin.aleo", - .function_name_length = 15, - .function_name = "transfer_public", - .inputs_count = 2, - .inputs - = {{.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x00"}, - {.value_length = 16, - .value - = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x01\x00\x0d"}}, - } + .fee_function_name = "fee_public", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", + .prepared_request = { + .program_id_length = 20, + .program_id = "usad_stablecoin.aleo", + .function_name_length = 15, + .function_name = "transfer_public", + .inputs_count = 2, + .inputs + = { + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x00" + }, + { + .value_length = 16, + .value + = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x01\x00\x0d" + } + }, + } }; assert_int_equal(tx_parse(&datas_token_public, &tx), 0); @@ -481,143 +547,274 @@ static void test_tx_token_parse(void **state) assert_int_equal(tx_parse(&datas_token_public, &tx), -1); datas_token_public.prepared_request.inputs[1].type_length = 3; - uint8_t type_1[3] = "\x01\x00\x0d"; - uint8_t type_2[3] = "\x02\x00\x0d"; - uint8_t type_3[3] = "\x01\x01\x0d"; + uint8_t type_1[3] = "\x01\x00\x0d"; + uint8_t type_2[3] = "\x02\x00\x0d"; + uint8_t type_3[3] = "\x01\x01\x0d"; datas_token_public.prepared_request.inputs[1].type = type_2; assert_int_equal(tx_parse(&datas_token_public, &tx), -1); datas_token_public.prepared_request.inputs[1].type = type_3; assert_int_equal(tx_parse(&datas_token_public, &tx), -1); datas_token_public.prepared_request.inputs[1].type = type_1; - uint8_t type_11[3] = "\x01\x00\x00"; - uint8_t type_12[3] = "\x02\x00\x00"; - char function_name_3[26] = "transfer_public_to_private"; + uint8_t type_11[3] = "\x01\x00\x00"; + uint8_t type_12[3] = "\x02\x00\x00"; + char function_name_3[26] = "transfer_public_to_private"; datas_token_public.prepared_request.function_name_length = sizeof(function_name_3); - datas_token_public.prepared_request.function_name = function_name_3; - datas_token_public.prepared_request.inputs[0].type = type_12; + datas_token_public.prepared_request.function_name = function_name_3; + datas_token_public.prepared_request.inputs[0].type = type_12; assert_int_equal(tx_parse(&datas_token_public, &tx), 0); datas_token_public.prepared_request.inputs[0].type = type_11; assert_int_equal(tx_parse(&datas_token_public, &tx), -1); const uint8_t hash_record_c[96] = "\xf4\x69\x19\x61\x50\x7b\x8f\x32\x92\xaf\x47\xac\x64\xdf\x59\xf7" - "\xc4\x39\xf6\xb2\x48\xa9\x55\x10\xfa\x95\xcc\x96\x25\xe7\xfd\x07" - "\x2a\xe1\x18\xb5\x2d\x46\xd6\x0b\x96\x63\x06\x72\x73\x3d\x25\x2c" - "\xa9\x3f\xbb\x8d\x56\xd5\x26\x1c\x0c\x4c\xbb\x8c\xf2\x92\x5d\x05" - "\xd9\x75\x64\x3e\x43\x24\x5c\x7a\xf2\x8d\xb2\xa8\x5b\x54\x59\xb4" - "\xb7\x7b\x38\x2a\x0c\x74\x33\x0c\x1d\x53\x7a\xa9\x22\xe1\x7c\x00"; - const uint8_t merkle_proof_c[32 * 32] = {0}; - uint8_t hash_record[96]; - uint8_t merkle_proof[32 * 32]; + "\xc4\x39\xf6\xb2\x48\xa9\x55\x10\xfa\x95\xcc\x96\x25\xe7\xfd\x07" + "\x2a\xe1\x18\xb5\x2d\x46\xd6\x0b\x96\x63\x06\x72\x73\x3d\x25\x2c" + "\xa9\x3f\xbb\x8d\x56\xd5\x26\x1c\x0c\x4c\xbb\x8c\xf2\x92\x5d\x05" + "\xd9\x75\x64\x3e\x43\x24\x5c\x7a\xf2\x8d\xb2\xa8\x5b\x54\x59\xb4" + "\xb7\x7b\x38\x2a\x0c\x74\x33\x0c\x1d\x53\x7a\xa9\x22\xe1\x7c\x00"; + const uint8_t merkle_proof_c[32 * 32] = {0}; + uint8_t hash_record[96]; + uint8_t merkle_proof[32 * 32]; sign_transaction_datas_t datas_token_private = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 11, - .fee_function_name = "fee_private", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", + .fee_function_name = "fee_private", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", .prepared_request - = {.program_id_length = 20, - .program_id = "usad_stablecoin.aleo", - .function_name_length = 16, - .function_name = "transfer_private", - .inputs_count = 4, - .inputs = { - {.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x00"}, - {.value_length = 16, - .value - = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x0d"}, - {.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x03\x07\x63\x72\x65\x64\x69\x74\x73"}, - {.value_length = 32 * 32, - .value = merkle_proof, - .type_length = 3, - .type = (uint8_t *) "\x02\x01\x00"}, - }} + = { + .program_id_length = 20, + .program_id = "usad_stablecoin.aleo", + .function_name_length = 16, + .function_name = "transfer_private", + .inputs_count = 4, + .inputs = { + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x00" + }, + { + .value_length = 16, + .value + = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x0d" + }, + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x03\x07\x63\x72\x65\x64\x69\x74\x73" + }, + { + .value_length = 32 * 32, + .value = merkle_proof, + .type_length = 3, + .type = (uint8_t*)"\x02\x01\x00" + }, + } + } }; memcpy(hash_record, hash_record_c, sizeof(hash_record)); memcpy(merkle_proof, merkle_proof_c, sizeof(merkle_proof)); assert_int_equal(tx_parse(&datas_token_private, &tx), 0); - char function_name_4[26] = "transfer_private_to_public"; + char function_name_4[26] = "transfer_private_to_public"; datas_token_private.prepared_request.function_name_length = sizeof(function_name_4); - datas_token_private.prepared_request.function_name = function_name_4; - datas_token_private.prepared_request.inputs[0].type = type_11; - datas_token_private.prepared_request.inputs[1].type = type_1; + datas_token_private.prepared_request.function_name = function_name_4; + datas_token_private.prepared_request.inputs[0].type = type_11; + datas_token_private.prepared_request.inputs[1].type = type_1; assert_int_equal(tx_parse(&datas_token_private, &tx), 0); datas_token_private.prepared_request.inputs[0].type = type_12; assert_int_equal(tx_parse(&datas_token_private, &tx), -1); sign_transaction_datas_t datas_token_batch_private = { - .max_base_fee = 100, - .max_priority_fee = 500, + .max_base_fee = 100, + .max_priority_fee = 500, .fee_function_name_length = 11, - .fee_function_name = "fee_private", - .fee_program_id_length = 12, - .fee_program_id = "credits.aleo", + .fee_function_name = "fee_private", + .fee_program_id_length = 12, + .fee_program_id = "credits.aleo", .prepared_request - = {.program_id_length = 18, - .program_id = "ldg_usad_p_28.aleo", - .function_name_length = 18, - .function_name = "transfer_private_2", - .inputs_count = 5, - .inputs = { - {.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x04"}, - {.value_length = 96, - .value = hash_record, - .type_length = 9, - .type = (uint8_t *) "\x04"}, - {.value_length = 32, - .value - = (uint8_t *) "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" - "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x00"}, - {.value_length = 16, - .value - = (uint8_t *) "\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .type_length = 3, - .type = (uint8_t *) "\x02\x00\x0d"}, - {.value_length = 32 * 32, - .value = merkle_proof, - .type_length = 3, - .type = (uint8_t *) "\x02\x01\x00"}, - }} + = { + .program_id_length = 18, + .program_id = "ldg_usad_p_28.aleo", + .function_name_length = 18, + .function_name = "transfer_private_2", + .inputs_count = 5, + .inputs = { + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x04" + }, + { + .value_length = 96, + .value = hash_record, + .type_length = 9, + .type = (uint8_t*)"\x04" + }, + { + .value_length = 32, + .value + = (uint8_t*)"\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x00" + }, + { + .value_length = 16, + .value + = (uint8_t*)"\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .type_length = 3, + .type = (uint8_t*)"\x02\x00\x0d" + }, + { + .value_length = 32 * 32, + .value = merkle_proof, + .type_length = 3, + .type = (uint8_t*)"\x02\x01\x00" + }, + } + } }; memcpy(hash_record, hash_record_c, sizeof(hash_record)); memcpy(merkle_proof, merkle_proof_c, sizeof(merkle_proof)); assert_int_equal(tx_parse(&datas_token_batch_private, &tx), 0); - char program_id_5[20] = "ldg_usad_p2p_28.aleo"; + char program_id_5[20] = "ldg_usad_p2p_28.aleo"; datas_token_batch_private.prepared_request.program_id_length = sizeof(program_id_5); - datas_token_batch_private.prepared_request.program_id = program_id_5; - char function_name_5[28] = "transfer_private_to_public_2"; + datas_token_batch_private.prepared_request.program_id = program_id_5; + char function_name_5[28] = "transfer_private_to_public_2"; datas_token_batch_private.prepared_request.function_name_length = sizeof(function_name_5); - datas_token_batch_private.prepared_request.function_name = function_name_5; - datas_token_batch_private.prepared_request.inputs[2].type = type_11; - datas_token_batch_private.prepared_request.inputs[3].type = type_1; + datas_token_batch_private.prepared_request.function_name = function_name_5; + datas_token_batch_private.prepared_request.inputs[2].type = type_11; + datas_token_batch_private.prepared_request.inputs[3].type = type_1; assert_int_equal(tx_parse(&datas_token_batch_private, &tx), 0); } +static void test_tx_parse_staking(void** state) +{ + (void)state; + tx_t tx; + + uint8_t addr_a[32] = "\x82\x48\xd5\xe8\x5a\xc4\xc1\x23\x46\xf8\x45\x8b\xd9\x39\xf1\xce" + "\x25\xae\x03\xe9\xc6\xcb\xc8\x86\x28\x6d\xf1\x61\x63\x0a\x75\x0c"; + uint8_t addr_b[32] = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"; + uint8_t amount_val[8] = "\xe8\x03\x00\x00\x00\x00\x00\x00"; // 1000 + uint8_t addr_type[3] = "\x01\x00\x00"; // public / plaintext / address + uint8_t u64_type[3] = "\x01\x00\x0c"; // public / plaintext / u64 + + // ---- bond_public: validator=addr_a (idx0), withdrawal=addr_b (idx1), amount (idx2) ---- + memset(&tx, 0, sizeof(tx)); + sign_transaction_datas_t datas_bond = { + .prepared_request = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 11, + .function_name = "bond_public", + .inputs_count = 3, + .inputs = { + {.value_length = 32, .value = addr_a, .type_length = 3, .type = addr_type}, + {.value_length = 32, .value = addr_b, .type_length = 3, .type = addr_type}, + {.value_length = 8, .value = amount_val, .type_length = 3, .type = u64_type} + }, + } + }; + assert_int_equal(tx_parse(&datas_bond, &tx), 0); + assert_int_equal(tx.type, TX_STAKING); + assert_int_equal(tx.staking.type, TX_STAKING_BOND); + assert_int_equal(tx.staking.amount, 1000); + // validator and withdrawal decode as distinct, full-length addresses + assert_int_equal(strlen(tx.staking.validator), ADDRESS_LEN); + assert_int_equal(strlen(tx.staking.withdrawal), ADDRESS_LEN); + assert_string_not_equal(tx.staking.validator, tx.staking.withdrawal); + char bond_validator[ADDRESS_LEN + 1]; + char bond_withdrawal[ADDRESS_LEN + 1]; + strncpy(bond_validator, tx.staking.validator, sizeof(bond_validator)); + strncpy(bond_withdrawal, tx.staking.withdrawal, sizeof(bond_withdrawal)); + + // Swap the two address inputs. validator must now hold what withdrawal held, + // proving inputs[0]->validator and inputs[1]->withdrawal (the security-critical + // mapping is not transposed by the parser). + memset(&tx, 0, sizeof(tx)); + datas_bond.prepared_request.inputs[0].value = addr_b; + datas_bond.prepared_request.inputs[1].value = addr_a; + assert_int_equal(tx_parse(&datas_bond, &tx), 0); + assert_string_equal(tx.staking.validator, bond_withdrawal); + assert_string_equal(tx.staking.withdrawal, bond_validator); + datas_bond.prepared_request.inputs[0].value = addr_a; + datas_bond.prepared_request.inputs[1].value = addr_b; + + // arity mismatch rejected by the generic dispatch loop + datas_bond.prepared_request.inputs_count = 2; + assert_int_equal(tx_parse(&datas_bond, &tx), -1); + datas_bond.prepared_request.inputs_count = 3; + + // ---- unbond_public: staker (idx0), amount (idx1) ---- + memset(&tx, 0, sizeof(tx)); + sign_transaction_datas_t datas_unbond = { + .prepared_request = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 13, + .function_name = "unbond_public", + .inputs_count = 2, + .inputs = { + {.value_length = 32, .value = addr_a, .type_length = 3, .type = addr_type}, + {.value_length = 8, .value = amount_val, .type_length = 3, .type = u64_type} + }, + } + }; + assert_int_equal(tx_parse(&datas_unbond, &tx), 0); + assert_int_equal(tx.type, TX_STAKING); + assert_int_equal(tx.staking.type, TX_STAKING_UNBOND); + assert_int_equal(tx.staking.amount, 1000); + assert_int_equal(strlen(tx.staking.staker), ADDRESS_LEN); + assert_string_equal(tx.staking.staker, bond_validator); // addr_a decodes consistently + + // ---- claim_unbond_public: staker (idx0), NO amount ---- + memset(&tx, 0, sizeof(tx)); + sign_transaction_datas_t datas_claim = { + .prepared_request = { + .program_id_length = 12, + .program_id = "credits.aleo", + .function_name_length = 19, + .function_name = "claim_unbond_public", + .inputs_count = 1, + .inputs = {{.value_length = 32, .value = addr_a, .type_length = 3, .type = addr_type}}, + } + }; + assert_int_equal(tx_parse(&datas_claim, &tx), 0); + assert_int_equal(tx.type, TX_STAKING); + assert_int_equal(tx.staking.type, TX_STAKING_CLAIM); + assert_string_equal(tx.staking.staker, bond_validator); + // claim must NOT populate amount (types.h: "claim leaves unset") + assert_int_equal(tx.staking.amount, 0); + // arity: claim with an extra input must be rejected + datas_claim.prepared_request.inputs_count = 2; + assert_int_equal(tx_parse(&datas_claim, &tx), -1); +} + int main() { - const struct CMUnitTest tests[] = {cmocka_unit_test(test_tx_extract), - cmocka_unit_test(test_tx_parse), - cmocka_unit_test(test_tx_token_parse)}; + const struct CMUnitTest tests[] + = { + cmocka_unit_test(test_tx_extract), + cmocka_unit_test(test_tx_parse), + cmocka_unit_test(test_tx_parse_staking),cmocka_unit_test(test_tx_extract), + cmocka_unit_test(test_tx_parse), + cmocka_unit_test(test_tx_token_parse) + }; return cmocka_run_group_tests(tests, NULL, NULL); }