From a6240f26d531ad042699973299211f89c1865600 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:31:17 -0600 Subject: [PATCH 1/6] Implement P2SH support --- src/address.c | 13 +++++++++-- src/sighash.c | 21 +++++++++++++----- src/transaction/deserialize.c | 34 +++++++++++++++++++++++----- src/transaction/serialize.c | 14 +++++++++--- src/transaction/types.h | 8 ++++--- src/transaction/utils.c | 8 +++++-- src/types.h | 3 ++- unit-tests/test_address.c | 20 ++++++++++++++++- unit-tests/test_tx_parser.c | 42 +++++++++++++++++++++++++++++++++++ 9 files changed, 139 insertions(+), 24 deletions(-) diff --git a/src/address.c b/src/address.c index e587ecb..55c41ab 100644 --- a/src/address.c +++ b/src/address.c @@ -35,15 +35,17 @@ size_t compress_public_key(const uint8_t public_key[static 64], address_type_e address_type, uint8_t *out) { size_t compressed_pub_size = 0; - if (address_type == SCHNORR) { + if (address_type == SCHNORR || address_type == P2SH) { compressed_pub_size = 32; memmove(out, public_key, 32); - } else { + } else if (address_type == ECDSA) { compressed_pub_size = 33; // If Y coord is even, first byte is 0x02. if odd then 0x03 out[0] = public_key[63] % 2 == 0 ? 0x02 : 0x03; // We copy starting from the 2nd byte memmove(out + 1, public_key, 32); + } else { + return 0; } return compressed_pub_size; @@ -61,6 +63,9 @@ bool address_from_pubkey(const uint8_t public_key[static 64], if (address_type == ECDSA) { address_len = ECDSA_ADDRESS_LEN; version = 1; + } else if (address_type == P2SH) { + address_len = SCHNORR_ADDRESS_LEN; + version = 8; } if (out_len < address_len) { @@ -79,6 +84,10 @@ bool address_from_pubkey(const uint8_t public_key[static 64], size_t compressed_pub_size = compress_public_key(public_key, address_type, compressed_public_key); + if (compressed_pub_size == 0) { + return false; + } + // First part of the address is "kaspa:" memmove(address, hrp, sizeof(hrp)); address[5] = ':'; diff --git a/src/sighash.c b/src/sighash.c index 9e464c9..f7153d3 100644 --- a/src/sighash.c +++ b/src/sighash.c @@ -122,12 +122,21 @@ static void calc_outputs_hash(transaction_t* tx, uint8_t* out_hash) { inner_buffer, 2); // Write the output script version, assume 0 - // First byte is always the length of the following public key - // Last byte is always 0xac (op code for normal transactions) - uint8_t script_len = tx->tx_outputs[i].script_public_key[0] + 2; - write_u64_le(inner_buffer, - 0, - script_len); // Write the number of bytes of the script public key + uint8_t script_len = 0; + if (tx->tx_outputs[i].script_public_key[0] == 0xaa) { + // P2SH script public key is always 35 bytes, + // always begins with 0xaa and ends with 0x87 + script_len = 35; + write_u64_le(inner_buffer, 0, 35); + } else { + // First byte is always the length of the following public key + // Last byte is always 0xac (op code for normal transactions) + script_len = tx->tx_outputs[i].script_public_key[0] + 2; + write_u64_le(inner_buffer, + 0, + script_len); // Write the number of bytes of the script public key + } + hash_update(&inner_hash_writer, inner_buffer, 8); hash_update(&inner_hash_writer, tx->tx_outputs[i].script_public_key, script_len); } diff --git a/src/transaction/deserialize.c b/src/transaction/deserialize.c index 687a548..8c8303b 100644 --- a/src/transaction/deserialize.c +++ b/src/transaction/deserialize.c @@ -34,8 +34,30 @@ parser_status_e transaction_output_deserialize(buffer_t *buf, transaction_output } size_t script_len = (size_t) * (buf->ptr + buf->offset); - // Can only be length 32 or 33. Fail it otherwise: - if (script_len == 0x20 || script_len == 0x21) { + + if (script_len == OP_BLAKE2B) { + // P2SH = 0xaa + 0x20 + (pubkey) + 0x87 + // script len is actually the second byte if the first one is 0xaa + script_len = (size_t) * (buf->ptr + buf->offset + 1); + + if (!buffer_can_read(buf, script_len + 3)) { + return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; + } + + uint8_t sig_op_code = *(buf->ptr + buf->offset + script_len + 2); + + if (script_len == 0x20 && sig_op_code != OP_EQUAL) { + return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; + } + + memcpy(txout->script_public_key, buf->ptr + buf->offset, script_len + 3); + + if (!buffer_seek_cur(buf, script_len + 3)) { + return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; + } + } else if (script_len == 0x20 || script_len == 0x21) { + // P2PK + // Can only be length 32 or 33. Fail it otherwise: if (!buffer_can_read(buf, script_len + 2)) { return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; } @@ -48,11 +70,11 @@ parser_status_e transaction_output_deserialize(buffer_t *buf, transaction_output } memcpy(txout->script_public_key, buf->ptr + buf->offset, script_len + 2); - } else { - return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; - } - if (!buffer_seek_cur(buf, script_len + 2)) { + if (!buffer_seek_cur(buf, script_len + 2)) { + return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; + } + } else { return OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR; } diff --git a/src/transaction/serialize.c b/src/transaction/serialize.c index da30e60..7d414f0 100644 --- a/src/transaction/serialize.c +++ b/src/transaction/serialize.c @@ -82,11 +82,19 @@ int transaction_output_serialize(const transaction_output_t *txout, uint8_t *out write_u64_be(out, offset, txout->value); offset += 8; - size_t script_len = txout->script_public_key[0]; + if (txout->script_public_key[0] == OP_BLAKE2B) { + size_t script_len = txout->script_public_key[1]; - memcpy(out + offset, txout->script_public_key, script_len + 2); + memcpy(out + offset, txout->script_public_key, script_len + 3); - offset += script_len + 2; + offset += script_len + 3; + } else { + size_t script_len = txout->script_public_key[0]; + + memcpy(out + offset, txout->script_public_key, script_len + 2); + + offset += script_len + 2; + } return (int) offset; } diff --git a/src/transaction/types.h b/src/transaction/types.h index f7048ff..49eaed2 100644 --- a/src/transaction/types.h +++ b/src/transaction/types.h @@ -60,8 +60,10 @@ typedef enum { * Enumeration of op codes */ typedef enum { - OP_CHECKSIG = 0xac, // Used for SCHNORR output - OP_CHECKSIGECDSA = 0xab // Used for ECDSA output + OP_CHECKSIG = 0xac, // Used for SCHNORR output + OP_CHECKSIGECDSA = 0xab, // Used for ECDSA output + OP_BLAKE2B = 0xaa, // Used for P2SH (start) + OP_EQUAL = 0x87 // Used for P2SH (end) } op_code_e; typedef struct { @@ -75,7 +77,7 @@ typedef struct { typedef struct { uint64_t value; - uint8_t script_public_key[35]; // In hex: 20 + public_key_hex + ac (34/35 bytes total) + uint8_t script_public_key[40]; // In hex: 20 + public_key_hex + ac (34/35 bytes total) } transaction_output_t; typedef struct { diff --git a/src/transaction/utils.c b/src/transaction/utils.c index 7fe4798..4a56eff 100644 --- a/src/transaction/utils.c +++ b/src/transaction/utils.c @@ -41,11 +41,15 @@ bool transaction_utils_check_encoding(const uint8_t* memo, uint64_t memo_len) { void script_public_key_to_address(uint8_t* out_address, uint8_t* in_script_public_key) { uint8_t public_key[64] = {0}; // public script keys begin with the length, followed by the amount of data - size_t data_len = (size_t) in_script_public_key[0]; + size_t first_byte = (size_t) in_script_public_key[0]; address_type_e type = SCHNORR; size_t address_len = SCHNORR_ADDRESS_LEN; - if (data_len == 0x21) { + if (first_byte == 0xaa) { + type = P2SH; + address_len = SCHNORR_ADDRESS_LEN; + memmove(public_key, in_script_public_key + 2, 32); + } else if (first_byte == 0x21) { // We're dealing with ECDSA instead: type = ECDSA; address_len = ECDSA_ADDRESS_LEN; diff --git a/src/types.h b/src/types.h index 7f9a56e..245e128 100644 --- a/src/types.h +++ b/src/types.h @@ -75,7 +75,8 @@ typedef enum { typedef enum { SCHNORR, // Display the 61 byte address for schnorr - ECDSA // Display the 63 byte address for ecdsa + ECDSA, // Display the 63 byte address for ecdsa + P2SH // Display the 61 byte address for p2sh (also schnorr) } address_type_e; /** diff --git a/unit-tests/test_address.c b/unit-tests/test_address.c index e0c0ad6..569f525 100644 --- a/unit-tests/test_address.c +++ b/unit-tests/test_address.c @@ -60,6 +60,23 @@ static void test_schnorr_address_from_public_key(void **state) { assert_string_equal((char *) address2, "kaspa:qrazhptjkcvrv23xz2xm8z8sfmg6jhxvmrscn7wph4k9we5tzxedwfxf0v6f8"); } +static void test_p2sh_address_from_public_key(void **state) { + uint8_t public_key[] = { + // OP_BLAKE2B, 0x20, + 0xF3, 0x80, 0x31, 0xF6, 0x1C, 0xA2, 0x3D, 0x70, 0x84, 0x4F, 0x63, 0xA4, 0x77, 0xD0, 0x7F, 0x0B, + 0x2C, 0x2D, 0xEC, 0xAB, 0x90, 0x7C, 0x2E, 0x09, 0x6E, 0x54, 0x8B, 0x0E, 0x08, 0x72, 0x1C, 0x79, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // OP_EQUAL + }; + + uint8_t address[SCHNORR_ADDRESS_LEN + 1] = {0}; + + address_from_pubkey(public_key, P2SH, address, SCHNORR_ADDRESS_LEN); + + assert_string_equal((char *) address, "kaspa:precqv0krj3r6uyyfa36ga7s0u9jct0v4wg8ctsfde2gkrsgwgw8jgxfzfc98"); +} + static void test_ecdsa_address_from_public_key(void **state) { // Even Y-coord test case uint8_t public_key_even[] = { @@ -92,7 +109,8 @@ static void test_ecdsa_address_from_public_key(void **state) { int main() { const struct CMUnitTest tests[] = {cmocka_unit_test(test_schnorr_address_from_public_key), - cmocka_unit_test(test_ecdsa_address_from_public_key)}; + cmocka_unit_test(test_ecdsa_address_from_public_key), + cmocka_unit_test(test_p2sh_address_from_public_key)}; return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/unit-tests/test_tx_parser.c b/unit-tests/test_tx_parser.c index d8c5d63..1c23655 100644 --- a/unit-tests/test_tx_parser.c +++ b/unit-tests/test_tx_parser.c @@ -259,6 +259,35 @@ static void test_tx_output_serialization_33_bytes(void **state) { assert_memory_equal(raw_tx, output, sizeof(raw_tx)); } +static void test_tx_output_serialization_p2sh(void **state) { + (void) state; + + transaction_output_t txout; + + // clang-format off + uint8_t raw_tx[] = { + // Output + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0xa0, + OP_BLAKE2B, 0x20, + 0xe1, 0x19, 0xd5, 0x35, 0x14, 0xc1, 0xb0, 0xe2, + 0xef, 0xce, 0x7a, 0x89, 0xe3, 0xd1, 0xd5, 0xd6, + 0xcd, 0x73, 0x58, 0x2e, 0xa2, 0x06, 0x87, 0x64, + 0x1c, 0x8f, 0xdc, 0xcb, 0x60, 0x60, 0xa9, 0xad, + OP_EQUAL + }; + + buffer_t buf = {.ptr = raw_tx, .size = sizeof(raw_tx), .offset = 0}; + + parser_status_e status = transaction_output_deserialize(&buf, &txout); + + assert_int_equal(status, PARSING_OK); + + uint8_t output[350]; + int length = transaction_output_serialize(&txout, output, sizeof(output)); + assert_int_equal(length, sizeof(raw_tx)); + assert_memory_equal(raw_tx, output, sizeof(raw_tx)); +} + static int run_test_tx_output_serialize(uint8_t* raw_tx, size_t raw_tx_len) { transaction_output_t txout; @@ -320,6 +349,17 @@ static void test_tx_output_deserialization_fail(void **state) { 0xcd, 0x73, 0x58, 0x2e, 0xa2, 0x06, 0x87, 0x64, }; + uint8_t invalid_p2sh_opcode[] = { + // Output + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0xa0, + OP_BLAKE2B, 0x20, + 0xe1, 0x19, 0xd5, 0x35, 0x14, 0xc1, 0xb0, 0xe2, + 0xef, 0xce, 0x7a, 0x89, 0xe3, 0xd1, 0xd5, 0xd6, + 0xcd, 0x73, 0x58, 0x2e, 0xa2, 0x06, 0x87, 0x64, + 0x1c, 0x8f, 0xdc, 0xcb, 0x60, 0x60, 0xa9, 0xad, + 0x00, OP_CHECKSIG + }; + uint8_t raw_tx[] = { // Output 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0xa0, @@ -335,6 +375,7 @@ static void test_tx_output_deserialization_fail(void **state) { assert_int_equal(run_test_tx_output_serialize(invalid_script_start, sizeof(invalid_script_start)), OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR); assert_int_equal(run_test_tx_output_serialize(invalid_script_end_ecdsa, sizeof(invalid_script_end_ecdsa)), OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR); assert_int_equal(run_test_tx_output_serialize(invalid_script_len, sizeof(invalid_script_len)), OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR); + assert_int_equal(run_test_tx_output_serialize(invalid_p2sh_opcode, sizeof(invalid_p2sh_opcode)), OUTPUT_SCRIPT_PUBKEY_PARSING_ERROR); } static void test_serialization_fail(void **state) { @@ -357,6 +398,7 @@ int main() { cmocka_unit_test(test_tx_input_deserialization_fail), cmocka_unit_test(test_tx_output_serialization_32_bytes), cmocka_unit_test(test_tx_output_serialization_33_bytes), + cmocka_unit_test(test_tx_output_serialization_p2sh), cmocka_unit_test(test_tx_output_deserialization_fail), cmocka_unit_test(test_serialization_fail)}; From d9d14fb274b642448b96663e9dda57882d88d0e3 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:31:38 -0600 Subject: [PATCH 2/6] Update p2sh python ftests --- tests/application_client/kaspa_transaction.py | 6 +- tests/test_sign_cmd.py | 56 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/tests/application_client/kaspa_transaction.py b/tests/application_client/kaspa_transaction.py index 07a5fa0..3a031a4 100644 --- a/tests/application_client/kaspa_transaction.py +++ b/tests/application_client/kaspa_transaction.py @@ -179,7 +179,11 @@ def _calc_outputs_hash(self) -> bytes: for txout in self.tx.outputs: inner_hash.update(txout.value.to_bytes(8, "little")) inner_hash.update((0).to_bytes(2, "little")) # assume script version 0 - inner_hash.update((txout.script_public_key[0] + 2).to_bytes(8, "little")) + if txout.script_public_key[0] == 0xaa: + inner_hash.update((35).to_bytes(8, "little")) + else: + inner_hash.update((txout.script_public_key[0] + 2).to_bytes(8, "little")) + inner_hash.update(txout.script_public_key) return inner_hash.digest() diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py index 669f0e4..9a09cba 100644 --- a/tests/test_sign_cmd.py +++ b/tests/test_sign_cmd.py @@ -66,6 +66,62 @@ def test_sign_tx_simple(firmware, backend, navigator, test_name): assert transaction.get_sighash(0) == sighash assert check_signature_validity(public_key, der_sig, sighash, transaction) +def test_sign_tx_p2sh(firmware, backend, navigator, test_name): + # Use the app interface instead of raw interface + client = KaspaCommandSender(backend) + # The path used for this entire test + path: str = "m/44'/111111'/0'/0/0" + + # First we need to get the public key of the device in order to build the transaction + rapdu = client.get_public_key(path=path) + _, public_key, _, _ = unpack_get_public_key_response(rapdu.data) + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + version=0, + inputs=[ + TransactionInput( + value=1100000, + tx_id="40b022362f1a303518e2b49f86f87a317c87b514ca0f3d08ad2e7cf49d08cc70", + address_type=0, + address_index=0, + index=0, + public_key=public_key[1:33] + ) + ], + outputs=[ + TransactionOutput( + value=1090000, + script_public_key="aa20f38031f61ca23d70844f63a477d07f0b2c2decab907c2e096e548b0e08721c7987" + ) + ] + ) + + # Send the sign device instruction. + # As it requires on-screen validation, the function is asynchronous. + # It will yield the result when the navigation is done + with client.sign_tx(transaction=transaction): + # Validate the on-screen request by performing the navigation appropriate for this device + if firmware.device.startswith("nano"): + navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, + [NavInsID.BOTH_CLICK], + "Approve", + ROOT_SCREENSHOT_PATH, + test_name) + else: + navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP, + [NavInsID.USE_CASE_REVIEW_CONFIRM, + NavInsID.USE_CASE_STATUS_DISMISS], + "Hold to sign", + ROOT_SCREENSHOT_PATH, + test_name) + + # The device as yielded the result, parse it and ensure that the signature is correct + response = client.get_async_response().data + _, _, _, der_sig, _, sighash = unpack_sign_tx_response(response) + assert transaction.get_sighash(0) == sighash + assert check_signature_validity(public_key, der_sig, sighash, transaction) + def test_sign_tx_simple_sendint(firmware, backend, navigator, test_name): # Use the app interface instead of raw interface client = KaspaCommandSender(backend) From 59d0d321bdee9d9215e2c2314ea2df5cb17c789e Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:31:46 -0600 Subject: [PATCH 3/6] Fix golden images --- .../snapshots/nanos/test_sign_tx_p2sh/00000.png | Bin 0 -> 379 bytes .../snapshots/nanos/test_sign_tx_p2sh/00001.png | Bin 0 -> 496 bytes .../snapshots/nanos/test_sign_tx_p2sh/00002.png | Bin 0 -> 521 bytes .../snapshots/nanos/test_sign_tx_p2sh/00003.png | Bin 0 -> 518 bytes .../snapshots/nanos/test_sign_tx_p2sh/00004.png | Bin 0 -> 443 bytes .../snapshots/nanos/test_sign_tx_p2sh/00005.png | Bin 0 -> 337 bytes .../snapshots/nanos/test_sign_tx_p2sh/00006.png | Bin 0 -> 313 bytes .../snapshots/nanos/test_sign_tx_p2sh/00007.png | Bin 0 -> 341 bytes .../snapshots/nanos/test_sign_tx_p2sh/00008.png | Bin 0 -> 411 bytes .../nanosp/test_sign_tx_p2sh/00000.png | Bin 0 -> 419 bytes .../nanosp/test_sign_tx_p2sh/00001.png | Bin 0 -> 980 bytes .../nanosp/test_sign_tx_p2sh/00002.png | Bin 0 -> 500 bytes .../nanosp/test_sign_tx_p2sh/00003.png | Bin 0 -> 395 bytes .../nanosp/test_sign_tx_p2sh/00004.png | Bin 0 -> 360 bytes .../nanosp/test_sign_tx_p2sh/00005.png | Bin 0 -> 364 bytes .../nanosp/test_sign_tx_p2sh/00006.png | Bin 0 -> 474 bytes .../snapshots/nanox/test_sign_tx_p2sh/00000.png | Bin 0 -> 419 bytes .../snapshots/nanox/test_sign_tx_p2sh/00001.png | Bin 0 -> 980 bytes .../snapshots/nanox/test_sign_tx_p2sh/00002.png | Bin 0 -> 500 bytes .../snapshots/nanox/test_sign_tx_p2sh/00003.png | Bin 0 -> 395 bytes .../snapshots/nanox/test_sign_tx_p2sh/00004.png | Bin 0 -> 360 bytes .../snapshots/nanox/test_sign_tx_p2sh/00005.png | Bin 0 -> 364 bytes .../snapshots/nanox/test_sign_tx_p2sh/00006.png | Bin 0 -> 474 bytes .../snapshots/stax/test_sign_tx_p2sh/00000.png | Bin 0 -> 10542 bytes .../snapshots/stax/test_sign_tx_p2sh/00001.png | Bin 0 -> 15419 bytes .../snapshots/stax/test_sign_tx_p2sh/00002.png | Bin 0 -> 11254 bytes .../snapshots/stax/test_sign_tx_p2sh/00003.png | Bin 0 -> 5086 bytes .../snapshots/stax/test_sign_tx_p2sh/00004.png | Bin 0 -> 10978 bytes 28 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00000.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00001.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00002.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00003.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00004.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00005.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00006.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00007.png create mode 100644 tests/snapshots/nanos/test_sign_tx_p2sh/00008.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00000.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00001.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00002.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00003.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00004.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00005.png create mode 100644 tests/snapshots/nanosp/test_sign_tx_p2sh/00006.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00000.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00001.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00002.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00003.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00004.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00005.png create mode 100644 tests/snapshots/nanox/test_sign_tx_p2sh/00006.png create mode 100644 tests/snapshots/stax/test_sign_tx_p2sh/00000.png create mode 100644 tests/snapshots/stax/test_sign_tx_p2sh/00001.png create mode 100644 tests/snapshots/stax/test_sign_tx_p2sh/00002.png create mode 100644 tests/snapshots/stax/test_sign_tx_p2sh/00003.png create mode 100644 tests/snapshots/stax/test_sign_tx_p2sh/00004.png diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00000.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..88429892f93b7b0e9cd223636a3660d85014331c GIT binary patch literal 379 zcmV->0fhdEP);X?a z0de~=yk>HjK6hmD2E_AklvVW+oNFx&=(6=+WpaQd|YZbwnuFqAP4RRg%|`$U)uhLCPG8^ zOXBrf4-Ln{Pe6(Ev6_h8n-1$B=jL#K4c%4%TOC>to9$P zF%dgE8H}05I{Q2zkoZNMPtXGc_6Q+KL1delFhs7OTvvBPvzM^72e}|27+iKDU+jm0 zVw{ZromodV&kA{f-&7SL8n0G}7%NPGo<52GP|SxQr;8`@=IOYiDXrZuURVVH00013 Zhz}pE2dC<=%dKn!vaU17O^>3!IFW|=KmZGDsTTQE7NZe$*JVsee%c=SLMx#(u zuTep{t&txhI0UhSKeDZK1RvB?H7Ly`J_J3ueT1?&^019*K&Qe}XW1s+0KAMKM=rj_ zQp9c7ILt)Ph%|s$2CJqTj@%e^?SLP`hCM(n&kj?s`U5~j!z+qQO2UP0!d3>b27IOV z_oSlg)c$1B1}n)Zw35Da_+=&$xwN~wYhG5Zq>7R80a4y$0JoadHHh1Y0ViUdk6eY> z2@y5YU{N!$`?r!TTd2sM++<2m#w~2v#n!6|q)F5}e;Yr{O-B>+?Ucpn#jY~(X5&u<0 mVzTI~i2d2>JWG-!iQylNQ*sQml1F_20000EeI@ literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00002.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..8ada47316bcc3f2cd1f7389d9f8fe94ff31045f3 GIT binary patch literal 521 zcmV+k0`~ohP)p64T;&0 zWD`;ps}0aRtfMF zer5FU2_w`Q{l&-}>_m2Qk$~%F)xb1*#GwxDOx@=5+!F9140f0rhve zfsjSDg}^lTASTWrmpVNnMBFNVgb}`qbD7T{_!B_p$2_m`OTAXdN7$OM-yIIJxgEsb z(U*MC(dP7un#k1FEA7%SS||ZjglSbXWx8AtJ?69ls^B)S8!=o^Gq@&nrE5K!U($o1 zdjlRKIQv-DRsu>R6Lcf>^mh=$3UOv_I?VVK0A9sZK&_4XS=7^-J5((3)jEbaYP2io zaX0g$(frhw2EFO25d29p(Zb;gYvmkKfMchJxu$o2A5J6^iN$yW77VXT-*Q^z00000 LNkvXXu0mjfm{jR1 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00003.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..b5655aaf871cb65ee60522a24bd3a652f781c763 GIT binary patch literal 518 zcmV+h0{Q)kP)+tr0raj!#MPg79ghUFEBuSDaf!uFxj}-Zl+3&Z%pE+IK zGFO=mJQpA>W2FPw7WU~v2mFSPF5UU-g3NiP zktgvJH#ER&Ljla$R=WAX;ReNM|=vJxP6eZO6Dm(h5?(RNL}Tdcn6ea1O@VQ zN0(X9ZPPe~g^>~I0JMx^8a5r7IjR=$zl3XlP|8Rx#cANRm_{Op$Sx zV?EtX3n;<@Q>&p$r9qPKn1Z#wzQuHbtvPC}7KD;U6Me-?DojV9S}7Gesz%eIMl9gP z8N8szrql(5P}NhAM+d)FiW-VCt-=B`A^=`npd=qu9Ij>9moUYwn9_H((&Asjc=ttk zw)T1kwQA}<$pXQDNhTIYf7jaQyZ>2zGpJQl_iI`pNs`3P1AQ6B@km^**#H0l07*qo IM6N<$f)pO^6951J literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00004.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..4ba0ac3c23a97dd53814a22411422b869acd8df0 GIT binary patch literal 443 zcmV;s0Yv_ZP)iwb@qI)=CCL?wOzaU=zB9LI4SE6$^?iILYDJ+9ieMaLm(!pMU*23DJ7FD4~RWVA6h04~623txK+ zM5*cmG3_uous!4_;F-C;~<%ck1kK`mf#dKKY^#7u=97UZ7T`i`4n9l%Q zZ|iA)S`w;u?ca>sU?d)eMl!`YEM99Hdgy884RWGP}Kw9179Rb&_Tgr(Dwi_cNT(f-k(%J;hy=ZGEE2y z5!Ky;b$+mtDGd;RAmlxCbWXpA5e5)LO4XT3lKAl}B$FCTmV~(VA$klem&W*C5st(* ldII@REAa4`;5d$B&IkLDI5*kiCyM|8002ovPDHLkV1fp-z9;|y literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00005.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00005.png new file mode 100644 index 0000000000000000000000000000000000000000..2f595a35ac872a9cfc3a87a3489b35908f59685f GIT binary patch literal 337 zcmV-X0j~auP)O41`n1zW)Pz&_fj|Ar$|z8MEK?0JKHAp@FU$AG7?FDsbudAn(8~l7$9L5LIPfgEwiCp zEl0N>YpD9vdo8~JKgBIKX6yw`cG5jH=y_~0xd8HlWylhxUNHAZ_?q5AS180y%4WyBJ1;~h}5t~U?K&hrmaPuA+Vfz08r`FDAgKEj&@3e3kG3;Uw!<7?GD0#`g}$#DKDk`?k;TuXbUnu zFtrY~Q*{7$8mc_l^L=%>1K=tCq$cr~p{m_hbS}Nu5kd$dgoNS+Ug^kBc~#C}00000 LNkvXXu0mjfB>jg? literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00007.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00007.png new file mode 100644 index 0000000000000000000000000000000000000000..66c411c2ebc833c701039f213ad4ff68cc881146 GIT binary patch literal 341 zcmV-b0jmCqP)_wxG+Yry2qARt#sf<#$}=)VJ~ zBlvESR-Jq3=$jydfC?r!$iuAw9oGJ!U-M%YMJ+y&Ch%TCM^JUq5BGkf8O_{y`#mQ} nq4{V^xv44i3V1v$0C_ea3_go|-rj`700000NkvXXu0mjfd&QW1 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanos/test_sign_tx_p2sh/00008.png b/tests/snapshots/nanos/test_sign_tx_p2sh/00008.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab62488898414fa0b4d01c83ce19cd254158238 GIT binary patch literal 411 zcmV;M0c8G(P)gPVv!e{1wVPd@+= z5p63?%kDA~#^XqG8AnQkpux7*a=%m`b>nhXOa>}oT51)*2kUw5D(;a!0ZQ+D)&Zmj zCFiNnEDg#$v+};Cb)1bt(4hY}-ni6)IunrBLCN&xlH2qyXB>Hlkl@KmC@;r_!*8I) zlh5hbx(yt*eFqUP$^=kEA6st)dkua9sB`}jH}Ebt(_ofEU^pz@nFZ-I@ScqKvp1Xl zB79bZ{w?6pvNKrI!s^9A?BOE;G%yW|p1lxDH2iZKfUf5^~(CIA4yGhfVf$DpW>Y_k9W002ovPDHLk FV1k#gxOo5o literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_tx_p2sh/00000.png b/tests/snapshots/nanosp/test_sign_tx_p2sh/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..df51419d9880ff10f1f24cebe779f11ff7ce27e0 GIT binary patch literal 419 zcmV;U0bKrxP)D$(iko|UTF@u&Yag{)@)mN`1iGamjW z?-@|#I%DcL`R;-Wx1m8iV&w2DI!Y>*e7y)ffN(0IS^hR>UWBs}p1R_IuO&=RwhCUX{fYF*|8$ z-}7I$&Jfhf0$I4MAmWJn3INi&qfcFT$NR000000000U?jMqbF~2?)b|e4* N002ovPDHLkV1ho3w>JO) literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_tx_p2sh/00001.png b/tests/snapshots/nanosp/test_sign_tx_p2sh/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..52c8036e0722e95bb943f828e18a96f941ff87a9 GIT binary patch literal 980 zcmV;_11tQAP)DOPJeXXR(CHG{v)En=9@V0J^T)k_3FG8O~S zU5+gs;FX(9XfvyyS(jd|)l77wt4A6aT7ZFey#yOOpoy5Q{V@wNq27uDbXCS$>^cL= zhC{Uqlql(wt}i>f)-S*ry6p7Np00(N`T{b{{zGCoyh-fp0J-5dgH3TUd+RCVy(wye z(C-QJ6+pU>gIAurS3tf)kLVrsehNdeZ`EN@L*Z z1_%`lmJ2$svVemGl%%P}$eS)gr_IINyN83PYl1XYnvhI`jCX{O8@%iu_h~BP5z}T^ zxumf70R-Gkd6I_!2+2g;0lJz(8B-v1v`-ydCd(7|#4uSMb3x}9BXXo+TC|L5XSfq3 z3Az?cU**^)8?0)NV59^H2wO20W$jywp?q!VegrbIzrzKH`TcY7a&M-uEAF5 z^!{0Bw~IExFLu~Y=!<-l?&6EO?04Cm1>ZC?G$iAZwBHp*NL2wvMhtO5CJSU%v7BP+ z)bu6)Y~B;bD9Pp#a6OtAL;0uH)%j_BE!fYy$VE@LSX81%A8Kpf#T!gvR+60UvM}5z z>wg<+deu~7NFS2rGq%q@=UrpVk8{VkS>5T{PLuBNYZDOOK!gmApWiWru>}jDX{H%U zEA%z2c-Kwd%+EQ?M75;@yloV(q81A)v{4~hNqlr`^7XX2ulNwcQ*pVATQ=ysPKAyC zACO>xZo*zW?`XiW+rwJd$p_^Uh^jV8~7&Y(^VHrbe?I&4*&Kp4wVC8TW_Rq+=1&&)s~kw_$d4gLW;gxp=APWeRu0000u>SBm|2)k_n006*iuY9I=R3SagIWQ#C8m^GS@0iGwN5#I9xlEI zh=hvXAnK+b+!}3GO|9>36p9n zY`vu0xAp{f+3Xek0QR`cq2PB+uP^pAE_*cZjz9jA4@Y>?S8Q?in4nH{t?9JYq7O{M z#+#3r?d#haQNb%@Je<8!dAX1W5E2Oh087f@ehCbLO*k8ql>#8AWK@Siux_iC4ThJ=g z8Niu%V%=p3Dox#WQTL!0y5j?=x6QVQT$=qR{j`yVxns>T4_@6B;%3pcB%Vu)SHW#i>o&3KStw=`ZBM6uWJSgd%F6$taD0e0sxC2ujv2) literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanosp/test_sign_tx_p2sh/00004.png b/tests/snapshots/nanosp/test_sign_tx_p2sh/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..848a5cea57d6c26be2fe8af6f1a3bc67c47d56ac GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|`huba4!+nDh2VBHtkep0-4j zdrQ9C2fcs9ujKeb!myEP-}&_?)59_L^LYMSxxp>3mB=vn)&j_W?hDl7dT+?%*l zU0P(pg!^JE&Au-9xs}y+uX=%hXz;9$4lbXjoIR+)tC!uJ-tf~rUwC5dyN16}0YCUm zSYwyWx$Y1;eeFRuT@6F$9F^U5|2eC-E~qiEdZ5Sybfx5{tBD`eqW8ae)m}MwwfN&- zSMrt9waQAnKDt#_=_Sp3WnZA#aDMiOtZL@I$%PsY^}qgK5SHNz$O&y*qw;g*j>*L} z+21l9(|FIUnf@w7dB@wfYti4LbK>~Sf7QK@{Ik^5^MBN4i+{NnEf-$D`{&5byJdpY z6(|2Qal5j_Uefe~i}FSd4J{-YHcY(QO5;J{<~e9q=7F?O4)!WO}6UUdH! zS+Hz=(4})vCM2-VD4nt3W%LdvkyzeG%km#`1t_mu*zR}#jNB{EKZnW}g5-=Bym-_% z`=7%C>zxJL|9msNSMXnbQRayy^)nr>EU7olTHqoc^vG(B%bo(Id*|kR{84!`z2x6n zZ`;PkbrPvd6U}A>Y0chs_tyHmLi6kw6c{>JvYiQ=+MTFTx8d*9^V|R0+_75oZt9or zLetinU!`YMvFyLCb8XxElhO0{v2rTkNR$jMW7~4}*8a52+MC^J%KMbxPN-JRb2RNP zEsp0ebAPS3=e2G53#Z$XZAI6Yd=Y%U^7k#000000058qS{=Y2rIfm# z#~2@u0o)_TXq5DtSpmxQkH6}x<U=PLxu-Mr%5Ugaaf2e?C2Z43Hv^6K`e1sm5f z#!kYe=2}W=63=LT%r`Eb0d`hE7?ow6HlA(fTpmGpv zk6MRAjegFUf008iW9~!6^t%;Me Q&Hw-a07*qoM6N<$g7a(EssI20 literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_tx_p2sh/00000.png b/tests/snapshots/nanox/test_sign_tx_p2sh/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..df51419d9880ff10f1f24cebe779f11ff7ce27e0 GIT binary patch literal 419 zcmV;U0bKrxP)D$(iko|UTF@u&Yag{)@)mN`1iGamjW z?-@|#I%DcL`R;-Wx1m8iV&w2DI!Y>*e7y)ffN(0IS^hR>UWBs}p1R_IuO&=RwhCUX{fYF*|8$ z-}7I$&Jfhf0$I4MAmWJn3INi&qfcFT$NR000000000U?jMqbF~2?)b|e4* N002ovPDHLkV1ho3w>JO) literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_tx_p2sh/00001.png b/tests/snapshots/nanox/test_sign_tx_p2sh/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..52c8036e0722e95bb943f828e18a96f941ff87a9 GIT binary patch literal 980 zcmV;_11tQAP)DOPJeXXR(CHG{v)En=9@V0J^T)k_3FG8O~S zU5+gs;FX(9XfvyyS(jd|)l77wt4A6aT7ZFey#yOOpoy5Q{V@wNq27uDbXCS$>^cL= zhC{Uqlql(wt}i>f)-S*ry6p7Np00(N`T{b{{zGCoyh-fp0J-5dgH3TUd+RCVy(wye z(C-QJ6+pU>gIAurS3tf)kLVrsehNdeZ`EN@L*Z z1_%`lmJ2$svVemGl%%P}$eS)gr_IINyN83PYl1XYnvhI`jCX{O8@%iu_h~BP5z}T^ zxumf70R-Gkd6I_!2+2g;0lJz(8B-v1v`-ydCd(7|#4uSMb3x}9BXXo+TC|L5XSfq3 z3Az?cU**^)8?0)NV59^H2wO20W$jywp?q!VegrbIzrzKH`TcY7a&M-uEAF5 z^!{0Bw~IExFLu~Y=!<-l?&6EO?04Cm1>ZC?G$iAZwBHp*NL2wvMhtO5CJSU%v7BP+ z)bu6)Y~B;bD9Pp#a6OtAL;0uH)%j_BE!fYy$VE@LSX81%A8Kpf#T!gvR+60UvM}5z z>wg<+deu~7NFS2rGq%q@=UrpVk8{VkS>5T{PLuBNYZDOOK!gmApWiWru>}jDX{H%U zEA%z2c-Kwd%+EQ?M75;@yloV(q81A)v{4~hNqlr`^7XX2ulNwcQ*pVATQ=ysPKAyC zACO>xZo*zW?`XiW+rwJd$p_^Uh^jV8~7&Y(^VHrbe?I&4*&Kp4wVC8TW_Rq+=1&&)s~kw_$d4gLW;gxp=APWeRu0000u>SBm|2)k_n006*iuY9I=R3SagIWQ#C8m^GS@0iGwN5#I9xlEI zh=hvXAnK+b+!}3GO|9>36p9n zY`vu0xAp{f+3Xek0QR`cq2PB+uP^pAE_*cZjz9jA4@Y>?S8Q?in4nH{t?9JYq7O{M z#+#3r?d#haQNb%@Je<8!dAX1W5E2Oh087f@ehCbLO*k8ql>#8AWK@Siux_iC4ThJ=g z8Niu%V%=p3Dox#WQTL!0y5j?=x6QVQT$=qR{j`yVxns>T4_@6B;%3pcB%Vu)SHW#i>o&3KStw=`ZBM6uWJSgd%F6$taD0e0sxC2ujv2) literal 0 HcmV?d00001 diff --git a/tests/snapshots/nanox/test_sign_tx_p2sh/00004.png b/tests/snapshots/nanox/test_sign_tx_p2sh/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..848a5cea57d6c26be2fe8af6f1a3bc67c47d56ac GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!2~2@x4h6`U|`huba4!+nDh2VBHtkep0-4j zdrQ9C2fcs9ujKeb!myEP-}&_?)59_L^LYMSxxp>3mB=vn)&j_W?hDl7dT+?%*l zU0P(pg!^JE&Au-9xs}y+uX=%hXz;9$4lbXjoIR+)tC!uJ-tf~rUwC5dyN16}0YCUm zSYwyWx$Y1;eeFRuT@6F$9F^U5|2eC-E~qiEdZ5Sybfx5{tBD`eqW8ae)m}MwwfN&- zSMrt9waQAnKDt#_=_Sp3WnZA#aDMiOtZL@I$%PsY^}qgK5SHNz$O&y*qw;g*j>*L} z+21l9(|FIUnf@w7dB@wfYti4LbK>~Sf7QK@{Ik^5^MBN4i+{NnEf-$D`{&5byJdpY z6(|2Qal5j_Uefe~i}FSd4J{-YHcY(QO5;J{<~e9q=7F?O4)!WO}6UUdH! zS+Hz=(4})vCM2-VD4nt3W%LdvkyzeG%km#`1t_mu*zR}#jNB{EKZnW}g5-=Bym-_% z`=7%C>zxJL|9msNSMXnbQRayy^)nr>EU7olTHqoc^vG(B%bo(Id*|kR{84!`z2x6n zZ`;PkbrPvd6U}A>Y0chs_tyHmLi6kw6c{>JvYiQ=+MTFTx8d*9^V|R0+_75oZt9or zLetinU!`YMvFyLCb8XxElhO0{v2rTkNR$jMW7~4}*8a52+MC^J%KMbxPN-JRb2RNP zEsp0ebAPS3=e2G53#Z$XZAI6Yd=Y%U^7k#000000058qS{=Y2rIfm# z#~2@u0o)_TXq5DtSpmxQkH6}x<U=PLxu-Mr%5Ugaaf2e?C2Z43Hv^6K`e1sm5f z#!kYe=2}W=63=LT%r`Eb0d`hE7?ow6HlA(fTpmGpv zk6MRAjegFUf008iW9~!6^t%;Me Q&Hw-a07*qoM6N<$g7a(EssI20 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_tx_p2sh/00000.png b/tests/snapshots/stax/test_sign_tx_p2sh/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..401fea2a573f9e4d7046db3f5b3be7886cf709f4 GIT binary patch literal 10542 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 K*Lc?V_WuEC{QQRi literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_tx_p2sh/00003.png b/tests/snapshots/stax/test_sign_tx_p2sh/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..7a05bf7b31c3fca94a4a464ad8709d1c20600e36 GIT binary patch literal 5086 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/stax/test_sign_tx_p2sh/00004.png b/tests/snapshots/stax/test_sign_tx_p2sh/00004.png new file mode 100644 index 0000000000000000000000000000000000000000..275ed2d3ba008adc49ada99899bc00b4eb5ac48d GIT binary patch literal 10978 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 e^Ae$7hfkQ;=+KEu=>G-7Z>t0V literal 0 HcmV?d00001 From df4d21e530042fe3846e3e382deec5ee457897cc Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Sun, 18 Jun 2023 16:22:19 -0600 Subject: [PATCH 4/6] Cover invalid address case --- unit-tests/test_address.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/unit-tests/test_address.c b/unit-tests/test_address.c index 569f525..4b4c2c4 100644 --- a/unit-tests/test_address.c +++ b/unit-tests/test_address.c @@ -107,10 +107,22 @@ static void test_ecdsa_address_from_public_key(void **state) { assert_string_equal((char *) address_odd, "kaspa:qyp7xyqdshh6aylqct7x2je0pse4snep8glallgz8jppyaajz7y7qeq4x79fq4z"); } +static void test_invalid_type(void **state) { + // Even Y-coord test case + uint8_t public_key[1] = {0}; + + uint8_t address[1] = {0}; + + bool res = address_from_pubkey(public_key, -1, address, 1); + + assert_int_equal(res, 0); +} + int main() { const struct CMUnitTest tests[] = {cmocka_unit_test(test_schnorr_address_from_public_key), cmocka_unit_test(test_ecdsa_address_from_public_key), - cmocka_unit_test(test_p2sh_address_from_public_key)}; + cmocka_unit_test(test_p2sh_address_from_public_key), + cmocka_unit_test(test_invalid_type)}; return cmocka_run_group_tests(tests, NULL, NULL); } From 009f8d84defca1bb63153fb27e0e931efb0d5b69 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:11:57 -0600 Subject: [PATCH 5/6] C unit test p2sh script scenario --- unit-tests/test_tx_utils.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/unit-tests/test_tx_utils.c b/unit-tests/test_tx_utils.c index cf47771..0ef0b46 100644 --- a/unit-tests/test_tx_utils.c +++ b/unit-tests/test_tx_utils.c @@ -61,6 +61,19 @@ static void test_script_public_key_to_address(void **state) { assert_string_equal((char *) schnorr_address, "kaspa:qrazhptjkcvrv23xz2xm8z8sfmg6jhxvmrscn7wph4k9we5tzxedwfxf0v6f8"); + uint8_t p2sh_spk[35] = { + OP_BLAKE2B, 0x20, + 0xF3, 0x80, 0x31, 0xF6, 0x1C, 0xA2, 0x3D, 0x70, 0x84, 0x4F, 0x63, 0xA4, 0x77, 0xD0, 0x7F, 0x0B, + 0x2C, 0x2D, 0xEC, 0xAB, 0x90, 0x7C, 0x2E, 0x09, 0x6E, 0x54, 0x8B, 0x0E, 0x08, 0x72, 0x1C, 0x79, + OP_EQUAL + }; + + uint8_t p2sh_address[68] = {0}; + + script_public_key_to_address(p2sh_address, p2sh_spk); + + assert_string_equal((char *) p2sh_address, "kaspa:precqv0krj3r6uyyfa36ga7s0u9jct0v4wg8ctsfde2gkrsgwgw8jgxfzfc98"); + uint8_t ecdsa_even_spk[35] = { 0x21, 0x02, 0xd5, 0xfd, 0xc7, 0xad, 0x11, 0xa6, 0x5d, 0x0b, From 18d2b1fb975f160e9093c435be7a338ee181c7f1 Mon Sep 17 00:00:00 2001 From: coderofstuff <114628839+coderofstuff@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:20:31 -0600 Subject: [PATCH 6/6] Update docs for P2SH support --- doc/COMMANDS.md | 2 +- doc/TRANSACTION.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/COMMANDS.md b/doc/COMMANDS.md index 175c8a2..334ad62 100644 --- a/doc/COMMANDS.md +++ b/doc/COMMANDS.md @@ -83,7 +83,7 @@ Transactions signed with ECDSA are currently not supported. | P1 Value | Usage | CData | | --- | --- | --- | | 0x00 | Sending transaction metadata | `version (2)` \|\| `output_len (1)` \|\| `input_len (1)` | -| 0x01 | Sending a tx output | `value (8)` \|\| `script_public_key (32/33)` | +| 0x01 | Sending a tx output | `value (8)` \|\| `script_public_key (34/35)` | | 0x02 | Sending a tx input | `value (8)` \|\| `tx_id (32)` \|\| `address_type (1)` \|\| `address_index (4)` \|\| `outpoint_index (1)` | | 0x03 | Requesting for next signature | - | diff --git a/doc/TRANSACTION.md b/doc/TRANSACTION.md index e2415e4..9bc76bc 100644 --- a/doc/TRANSACTION.md +++ b/doc/TRANSACTION.md @@ -10,7 +10,7 @@ The base unit in Kaspa is the KAS and the smallest unit used in raw transaction ## Address format -Kaspa addresses begin with `kaspa:` followed by 61 base32 characters for a total of `67` bytes for Schnorr-signed addresses. +Kaspa addresses begin with `kaspa:` followed by 61 base32 characters for a total of `67` bytes for Schnorr-signed and P2SH addresses. P2SH addresses are supported only as a send address by this app. For ECDSA-signed addresses (supported by this app only as a send address), it begins with `kaspa:` followed by 63 bytes for a total of `69` bytes. @@ -54,7 +54,7 @@ Total bytes: 43 (max) | Field | Size (bytes) | Description | | --- | --- | --- | | `value` | 8 | The amount of KAS in sompi that will go send to the address | -| `script_public_key` | 35 | Schnorr: `20` + public_key (32 bytes) + `ac`
ECDSA: `20` + public_key (33 bytes) + `ab` | +| `script_public_key` | 35 | Schnorr: `20` + public_key (32 bytes) + `ac`
ECDSA: `20` + public_key (33 bytes) + `ab`
P2SH: `aa20` + public_key (32 bytes) + `87` | ### Transaction Requirements - Fee = (total inputs amount) - (total outputs amount)