From 0c44680b35b318b5bb4eb2049c85022fe712087c Mon Sep 17 00:00:00 2001
From: coderofstuff <114628839+coderofstuff@users.noreply.github.com>
Date: Sat, 14 Oct 2023 23:30:50 -0600
Subject: [PATCH] Allow generating the xpub for root node
---
doc/COMMANDS.md | 17 +++++++++++------
src/handler/get_public_key.c | 7 +------
src/sw.h | 3 +--
.../application_client/kaspa_command_sender.py | 3 +--
tests/test_pubkey_cmd.py | 6 +++---
5 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/doc/COMMANDS.md b/doc/COMMANDS.md
index 0aa991c..ef049a2 100644
--- a/doc/COMMANDS.md
+++ b/doc/COMMANDS.md
@@ -47,15 +47,21 @@ Raw response looks like: `4b617370619000`
| --- | --- | --- | --- | --- | --- |
| 0xE0 | 0x05 | 0x00 (no display)
0x01 (display) | 0x00 | 0x15 | `path len (1 byte)` \|\|
`purpose (4 bytes)` \|\|
`coin_type (4 bytes)` \|\|
`account (4 bytes)` \|\|
`type (4 bytes)` \|\|
`index (4 bytes)` |
-Keys for kaspa use the derivation path `m/44'/111111'/'//`.
+Keys for kaspa normally use the derivation path `m/44'/111111'/'//`. This command will accept these as inputs:
+- `m/44'/111111'`
+- `m/44'/111111'/'`
+- `m/44'/111111'/'/`
+- `m/44'/111111'/'//`
| CData Part | Description |
| --- | --- |
| `purpose` | Must be `44'` or `80000002c` |
| `coin_type` | Must be `111111'` or `8001b207` |
-| `account` | Current wallets all use `80000000` for `0'` for default account but any value is accepted |
-| `type` | Either `00000000` for Receive Address or `00000001` for Change Address |
-| `index` | Any value from `00000000` to `11111111` |
+| `account` | Current wallets all use `80000000` (aka. `0'`) for default account but any value from `00000000` to `11111111` is accepted if passed |
+| `type` | Current wallets use either `00000000` for Receive Address or `00000001` for Change Address, but any value from `00000000` to `11111111` is accepted if passed |
+| `index` | Any value from `00000000` to `11111111` if passed |
+
+If you want to generate addresses using a root public key,
### Response
@@ -171,8 +177,7 @@ Transactions signed with ECDSA are currently not supported.
| 0xB008 | `SW_SIGNATURE_FAIL` | Signature of raw transaction failed |
| 0xB009 | `SW_WRONG_BIP32_PURPOSE` | `Purpose` must be `44'` |
| 0xB00A | `SW_WRONG_BIP32_COIN_TYPE` | `Coin Type` must be `111111'` |
-| 0xB00B | `SW_WRONG_BIP32_TYPE` | `Type` passed is not valid. Must be either `0` for `Receive` or `1` for `Change`|
-| 0xB00C | `SW_WRONG_BIP32_PATH_LEN` | Path length must be `5` |
+| 0xB00B | `SW_WRONG_BIP32_PATH_LEN` | Path length must be `5` |
| 0xB010 | `SW_MESSAGE_PARSING_FAIL` | Unable to parse message data |
| 0xB011 | `SW_MESSAGE_TOO_LONG` | Message len greater than max |
| 0xB012 | `SW_MESSAGE_TOO_SHORT` | Message len is 0 |
diff --git a/src/handler/get_public_key.c b/src/handler/get_public_key.c
index fd574eb..f559efb 100644
--- a/src/handler/get_public_key.c
+++ b/src/handler/get_public_key.c
@@ -51,7 +51,7 @@ int handler_get_public_key(buffer_t *cdata, bool display) {
return io_send_sw(SW_WRONG_DATA_LENGTH);
}
- if (G_context.bip32_path_len != 5) {
+ if (G_context.bip32_path_len < 2 || G_context.bip32_path_len > 5) {
return io_send_sw(SW_WRONG_BIP32_PATH_LEN);
}
@@ -63,11 +63,6 @@ int handler_get_public_key(buffer_t *cdata, bool display) {
return io_send_sw(SW_WRONG_BIP32_COIN_TYPE);
}
- if (G_context.bip32_path[3] != (uint32_t) RECEIVE &&
- G_context.bip32_path[3] != (uint32_t) CHANGE) {
- return io_send_sw(SW_WRONG_BIP32_TYPE);
- }
-
int error = bip32_derive_get_pubkey_256(CX_CURVE_256K1,
G_context.bip32_path,
G_context.bip32_path_len,
diff --git a/src/sw.h b/src/sw.h
index a60be47..7adffdf 100644
--- a/src/sw.h
+++ b/src/sw.h
@@ -86,8 +86,7 @@
#define SW_WRONG_BIP32_PURPOSE 0xB009
#define SW_WRONG_BIP32_COIN_TYPE 0xB00A
-#define SW_WRONG_BIP32_TYPE 0xB00B
-#define SW_WRONG_BIP32_PATH_LEN 0xB00C
+#define SW_WRONG_BIP32_PATH_LEN 0xB00B
#define SW_MESSAGE_PARSING_FAIL 0xB010
#define SW_MESSAGE_TOO_LONG 0xB011
#define SW_MESSAGE_TOO_SHORT 0xB012
diff --git a/tests/application_client/kaspa_command_sender.py b/tests/application_client/kaspa_command_sender.py
index e5af126..c6abd06 100644
--- a/tests/application_client/kaspa_command_sender.py
+++ b/tests/application_client/kaspa_command_sender.py
@@ -54,8 +54,7 @@ class Errors(IntEnum):
SW_SIGNATURE_FAIL = 0xB008
SW_WRONG_BIP32_PURPOSE = 0xB009
SW_WRONG_BIP32_COIN_TYPE = 0xB00A
- SW_WRONG_BIP32_TYPE = 0xB00B
- SW_WRONG_BIP32_PATH_LEN = 0xB00C
+ SW_WRONG_BIP32_PATH_LEN = 0xB00B
SW_MESSAGE_PARSING_FAIL = 0xB010
SW_MESSAGE_TOO_LONG = 0xB011
SW_MESSAGE_TOO_SHORT = 0xB012
diff --git a/tests/test_pubkey_cmd.py b/tests/test_pubkey_cmd.py
index c9809c4..d1d56bf 100644
--- a/tests/test_pubkey_cmd.py
+++ b/tests/test_pubkey_cmd.py
@@ -8,7 +8,7 @@
# GET_PUBLIC_KEY works for valid cases in non-confirmation mode
def test_get_public_key_no_confirm_valid(backend):
- for path in ["m/44'/111111'/0'/0/0", "m/44'/111111'/0/0/0", "m/44'/111111'/911'/0/0", "m/44'/111111'/0/1/255", "m/44'/111111'/2147483647/0/0"]:
+ for path in ["m/44'/111111'/0'/0/0", "m/44'/111111'/0/0/0", "m/44'/111111'/911'/0/0", "m/44'/111111'/0/1/255", "m/44'/111111'/2147483647/0/0", "m/44'/111111'/0'/0/0", "m/44'/111111'/911'/3/0", "m/44'/111111'"]:
client = KaspaCommandSender(backend)
response = client.get_public_key(path=path).data
_, public_key, _, chain_code = unpack_get_public_key_response(response)
@@ -24,8 +24,8 @@ def test_get_public_key_no_confirm_invalid(backend):
for test_case in [
("m/33'/0'/0'/0/0", Errors.SW_WRONG_BIP32_PURPOSE),
("m/44'/0'/0/0/0", Errors.SW_WRONG_BIP32_COIN_TYPE),
- ("m/44'/111111'/911'/3/0", Errors.SW_WRONG_BIP32_TYPE),
- ("m/44'/111111'/2147483647/0", Errors.SW_WRONG_BIP32_PATH_LEN)
+ ("m/44'", Errors.SW_WRONG_BIP32_PATH_LEN),
+ ("m/44'/111111'/2147483647/0/0/0", Errors.SW_WRONG_BIP32_PATH_LEN)
]:
client = KaspaCommandSender(backend)