APDU requests - SkycoinProject/ledger-nano GitHub Wiki
APDU (Application Protocol Data Unit)
In the Ledger app, each command/response packet is called an APDU. The application is driven by a never-ending APDU interpretation loop called straight from the application main function. More about APDU: good overview, wiki page, ledger app structure and I/O
BIP44 path
For nearly every call you need to send BIP44 address, which consists of 5 levels, 4 bytes each.
(m / purpose / coin_type / account / change / address_index)
Purpose is always equal to 0x8000002C. Coin_type is always equal to (Skycoin doesn't register their coin_type). You can use account different for your purpose, so you use just 0. As the address will be seen outside the wallet in Ledger app, so change has to be 0. For address_index you can just use 0. More about BIP44.
Implemented APDUs:
1. Get Skycoin public key:
This command returns the compressed public key for the given BIP44 path. After that you can check your skycoin address in main menu -> settings -> address
.
Description:
- Command
CLA | INS | P1 | P2 | Lc | Le |
---|---|---|---|---|---|
A1 | 0x04 |
- Input data
Description | Length |
---|---|
BIP44 address | 20 |
- Output data
Description | Length |
---|---|
Public key | 33 |
2. Get signed public key:
This command returns signed public key, so companion app can check, that Ledger device is genuine. More details on Ledger documentation.
Description:
- Command
CLA | INS | P1 | P2 | Lc | Le |
---|---|---|---|---|---|
A1 | 0x08 |
- Input data
Description | Length |
---|---|
BIP44 address | 20 |
- Output data
Description | Length |
---|---|
Signed public key | 65 |
(more about signing here)
3. Get Skycoin address:
This command returns the skycoin address from your public key.
Important: it will also store the BIP44 path to the memory
Description:
- Command
CLA | INS | P1 | P2 | Lc | Le |
---|---|---|---|---|---|
A1 | 0x02 |
- Input data
Description | Length |
---|---|
BIP44 address | 20 |
- Output data
Description | Length |
---|---|
Address | 36 |
4. Sign transaction:
This command gets a raw transaction as an input data and returns a signed transaction (which is ready to be broadcasted throughout the blockchain)
Important: we do not send BIP44 path here so you need to call "Get Skycoin Address" firstly, so the path will be stored and could be used for signing
Description:
- Command
CLA | INS | P1 | P2 | Lc | Le |
---|---|---|---|---|---|
A1 | 0x10 |
- Input data
Description | Length |
---|---|
Input num | 4 |
Input* | 32 |
Address index | 4 |
Ouput num | 4 |
Ouput* | 37 |
- Output data
Description | Length |
---|---|
Inner Hash | 32 |
Signed input* | 65 |
According to BIP44 standard, you can use different accounts and address indexes and each of them has another public key, so inputs related to different paths should be signed with different public keys. Also, BIP44 says, that one transaction should have addresses only from on account, so for each input, we need to know only new address index. But Ledger should know the account index, so before signing transactions, you should use getPublicKey or getAddress.
If signing process will be canceled, then you will get 0x6B0 as an error status code
Note: "*" - array of such objects
Check python scripts: generating_txn.py and sign_transaction.py to get more understanding of how transaction should be sended and then how to receive its signature
5. Get app version:
This command returns the version of Ledger app.
Description:
- Command
CLA | INS | P1 | P2 | Lc | Le |
---|---|---|---|---|---|
A1 | 0x01 |
- Output data
Description | Length |
---|---|
App version | 3 |
Example of ADPU call
Let's get our Skycoin address from ADPU call using BIP44 path 8000002 / C80000378 / 00000000 / 00000000/ 00000000
CLA | INS | P1 | P2 | Lc | Data field | Le |
---|---|---|---|---|---|---|
0x80 | 0x02 | 0x00 | 0x00 | 0x14 | 8000002C80000378000000000000000000000000 | 0x24 |
So, our request will have a format
80020000148000002C8000037800000000000000000000000024
From Ledger we will get
323536544632453176784a7831355779686567516f55795150424d31386e7264634a429000
And then after transforming bytes to the string we will get
256TF2E1vxJx15WyhegQoUyQPBM18nrdcJB