Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow generating the xpub for root node #54

Merged
merged 1 commit into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions doc/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,21 @@ Raw response looks like: `4b617370619000`
| --- | --- | --- | --- | --- | --- |
| 0xE0 | 0x05 | 0x00 (no display) <br> 0x01 (display) | 0x00 | 0x15 | `path len (1 byte)` \|\|<br>`purpose (4 bytes)` \|\|<br> `coin_type (4 bytes)` \|\|<br> `account (4 bytes)` \|\|<br> `type (4 bytes)` \|\|<br>`index (4 bytes)` |

Keys for kaspa use the derivation path `m/44'/111111'/<account>'/<type>/<index>`.
Keys for kaspa normally use the derivation path `m/44'/111111'/<account>'/<type>/<index>`. This command will accept these as inputs:
- `m/44'/111111'`
- `m/44'/111111'/<account>'`
- `m/44'/111111'/<account>'/<type>`
- `m/44'/111111'/<account>'/<type>/<index>`

| 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

Expand Down Expand Up @@ -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 |
Expand Down
7 changes: 1 addition & 6 deletions src/handler/get_public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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,
Expand Down
3 changes: 1 addition & 2 deletions src/sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions tests/application_client/kaspa_command_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions tests/test_pubkey_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)

Expand Down
Loading