The general structure of commands and responses is as follows:
Field |
Type |
Content |
Note |
CLA |
byte (1) |
Application Identifier |
0x59 |
INS |
byte (1) |
Instruction ID |
|
P1 |
byte (1) |
Parameter 1 |
|
P2 |
byte (1) |
Parameter 2 |
|
L |
byte (1) |
Bytes in payload |
|
PAYLOAD |
byte (L) |
Payload |
|
Field |
Type |
Content |
Note |
ANSWER |
byte (?) |
Answer |
depends on the command |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Return code |
Description |
0x6400 |
Execution Error |
0x6700 |
Wrong buffer length |
0x6982 |
Empty buffer |
0x6983 |
Output buffer too small |
0x6984 |
Data is invalid |
0x6986 |
Command not allowed |
0x6987 |
Tx is not initialized |
0x6B00 |
P1/P2 are invalid |
0x6D00 |
INS not supported |
0x6E00 |
CLA not supported |
0x6F00 |
Unknown |
0x6F01 |
Sign / verify error |
0x9000 |
Success |
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0xE0 |
INS |
byte (1) |
Instruction ID |
0x01 |
P1 |
byte (1) |
Parameter 1 |
0x00 |
P2 |
byte (1) |
Parameter 2 |
0x00 |
L |
byte (1) |
Bytes in payload |
0x00 |
Field |
Type |
Content |
Note |
TARGET_ID |
byte (4) |
Target Id |
|
OS_LEN |
byte (1) |
OS version length |
0..64 |
OS |
byte (?) |
OS version |
Non terminated string |
FLAGS_LEN |
byte (1) |
Flags length |
0 |
MCU_LEN |
byte (1) |
MCU version length |
0..64 |
MCU |
byte (?) |
MCU version |
Non terminated string |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0x00 |
P1 |
byte (1) |
Parameter 1 |
ignored |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
0 |
Field |
Type |
Content |
Note |
TEST |
byte (1) |
Test Mode |
0x01 means test mode is enabled |
MAJOR |
byte (2) |
Version Major |
0..65535 |
MINOR |
byte (2) |
Version Minor |
0..65535 |
PATCH |
byte (2) |
Version Patch |
0..65535 |
LOCKED |
byte (1) |
Device is locked |
It'll always be 0 |
TARGET_ID |
byte (4) |
Target Id |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0x01 |
P1 |
byte (1) |
Request User confirmation |
No = 0 |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
(depends) |
Path[0] |
byte (4) |
Derivation Path Data |
0x8000002c |
Path[1] |
byte (4) |
Derivation Path Data |
0x80000085 |
Path[2] |
byte (4) |
Derivation Path Data |
? |
Path[3] |
byte (4) |
Derivation Path Data |
? |
Path[4] |
byte (4) |
Derivation Path Data |
? |
Field |
Type |
Content |
Note |
Compressed PK |
byte (33) |
Public Key |
|
ADDR |
byte (??) |
address |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Returns or shows a shielded address with default diversifier (z-address)
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0x11 |
P1 |
byte (1) |
Request User confirmation |
No = 0 |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
always 4 |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
Field |
Type |
Content |
Note |
ADDR_RAW |
byte (43) |
Raw address |
|
ADDR_BECH32 |
byte (variable) |
Bech32 encoding of address |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Returns a shielded address using a specific diversifier
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0x10 |
P1 |
byte (1) |
Request User confirmation |
No = 0 |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
always 15 |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
DIV |
byte (11) |
Diversifier |
11-bytes |
Field |
Type |
Content |
Note |
ADDR_RAW |
byte (43) |
Diversifier (11) + pubkeyDiv(32) |
|
ADDR_BECH32 |
byte (43) |
Bech32 encoding of raw address |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
On input of a 11-byte starting index, get all valid diversifiers in the 20 indexes after (including starting index).
If a diversifier was not valid, zero-bytes are returned (so always 220 bytes are returned).
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0x09 |
P1 |
byte (1) |
Parameter 1 |
ignored |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
(depends) |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
DIV |
byte (11) |
Starting index search |
11-bytes |
Field |
Type |
Content |
Note |
DIV_LIST_RAW |
byte (220) |
List of raw diversifiers |
11-bytes each |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Returns a sapling incoming viewing key.
Forced user confirmation (So P1 needs to be 0x01).
Also returns the default diversifier (starting from index 0).
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xf0 |
P1 |
byte (1) |
Ignored |
ignored |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
(depends) |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
Field |
Type |
Content |
Note |
IVK_RAW |
byte (32) |
Raw IVK |
|
DIV |
byte (11) |
Default diversifier |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Returns a sapling outgoing viewing key. Forced user confirmation (So P1 needs to be 0x01).
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xf1 |
P1 |
byte (1) |
Ignored |
ignored |
P2 |
byte (1) |
Ignored |
ignored |
L |
byte (1) |
Bytes in payload |
(depends) |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
Field |
Type |
Content |
Note |
OVK_RAW |
byte (32) |
Raw OVK |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Returns a sapling full viewing key fvk = (ak, nk, ovk). Forced user confirmation (So P1 needs to be 0x01).
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xf3 |
P1 |
byte (1) |
Request User confirmation |
always 1 or error |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
(depends) |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
Field |
Type |
Content |
Note |
AK_RAW |
byte (32) |
Raw AK |
|
NK_RAW |
byte (32) |
Raw NK |
|
OVK_RAW |
byte (32) |
Raw OVK |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Returns a sapling nullifier. TODO: Forced user confirmation (So P1 needs to be 0x01).
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xf2 |
P1 |
byte (1) |
Ignored |
ignored |
P2 |
byte (1) |
Ignored |
ignored |
L |
byte (1) |
Bytes in payload |
(depends) |
ZIP32-account |
byte (4) |
Derivation Path Data |
u32 Little-Endian |
POSITION |
byte (8) |
Note position |
uint64 |
CM |
byte(32) |
Note commitment Data |
32-bytes |
Field |
Type |
Content |
Note |
NF_RAW |
byte (32) |
Raw NF |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Initiates a transaction for sapling. The init_message should have the following format:
Type |
Content |
Expected |
byte (1) |
t_in_len: number of transparent inputs |
0x00 - 0x05 |
byte (1) |
t_out_len: number of transparent outputs |
0x00 - 0x05 |
byte (1) |
s_in_len: number of shielded spends |
0x00 - 0x05 |
byte (1) |
s_out_len: number of shielded outputs |
0x00 - 0x05 |
byte (variable) |
transparent input data = [t_in] |
t_in_len * 54 bytes |
byte (variable) |
transparent output data = [t_out] |
t_out_len * 34 bytes |
byte (variable) |
shielded spend data = [s_spend] |
s_in_len * 55 bytes |
byte (variable) |
shielded output data = [s_out] |
s_out_len * 85 bytes |
where
t_in :
Type |
Content |
Expected |
byte (20) |
Derivation path data |
5 times 4 bytes |
byte (26) |
Script of transparent input |
|
byte (8) |
transparent input value |
u64 |
t_out :
Type |
Content |
Expected |
byte (26) |
Script of transparent output |
|
byte (8) |
transparent output value |
u64 |
s_spend:
Type |
Content |
Expected |
byte (4) |
ZIP32-path (hardened only) |
u32 |
byte (43) |
Shielded spend address |
|
byte (8) |
Shielded spend value |
u64 |
s_output:
Type |
Content |
Expected |
byte (43) |
Shielded output address |
|
byte (8) |
Shielded output value |
u64 |
byte (1) |
Shielded output memo type |
0xf6 for default memo |
byte (32) |
Shielded output OVK |
32 zero-bytes for non-OVK |
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xa0 |
P1 |
byte (1) |
Payload desc |
0 = init |
|
|
|
1 = add |
|
|
|
2 = last |
P2 |
byte (1) |
TxVersion |
4 = Sapling |
|
|
|
5 = NU5 |
L |
byte (1) |
Bytes in payload |
(depends) |
The first packet/chunk includes only the derivation path
All other packets/chunks contain data chunks that are described below
First Packet
Field |
Type |
Content |
Expected |
Other Chunks/Packets
Field |
Type |
Content |
Expected |
Data |
bytes... |
Message |
|
Data is defined as:
Field |
Type |
Content |
Expected |
Message |
bytes.. |
init_message bytes as defined above |
|
Field |
Type |
Content |
Note |
hash |
byte (32) |
Hash of init_message |
SHA256-hash |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
INS_EXTRACT_SPEND
Returns a proof generating key (PGK) and randomness (rcv and alpha) for a sapling spend.
- This command requires you already called the INS_INIT_TX.
- This command requires that it is needed to extract spendinfo.
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xa1 |
P1 |
byte (1) |
Parameter 1 |
ignored |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
0 (empty) |
Field |
Type |
Content |
Note |
PGK_RAW |
byte (64) |
Raw PGK |
32 byte representations for ak, nsk |
rcv_RAW |
byte (32) |
Raw rcv |
|
alpha_RAW |
byte (32) |
Raw alpha |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
INS_EXTRACT_OUTPUT
Returns randomness (rcv and rseed (after ZIP202) and optional Hash_Seed) for a sapling output.
- This command requires you already called the INS_INIT_TX.
- This command requires you already called the correct number of INS_GET_SPENDINFO.
- This command requires that it is needed to extract outputinfo.
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xa2 |
P1 |
byte (1) |
Parameter 1 |
ignored |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
0 (empty) |
Field |
Type |
Content |
Note |
rcv_RAW |
byte (32) |
Raw rcv |
|
rseed_RAW |
byte (32) |
Raw rseed |
|
hash_seed |
byte (32) |
Raw hash_seed |
Only returned if OVK=None for this output |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Checks the transaction data and signs if it is correct with the corresponding keys.
- This command requires you already called the INS_INIT_TX
- This command requires you already called the correct number of INS_EXTRACT_SPEND.
- This command requires you already called the correct number of INS_EXTRACT_OUTPUT.
- Due to the complexity of this command, if an error is detected throughout the entire verification process, the
response will consist only of the return code.
The transaction_blob should have the following format:
Type |
Content |
Expected |
byte (variable) |
transparent data to check |
t_in_len * 74 bytes |
byte (variable) |
previous spend data to check |
s_in_len* 40 bytes |
byte (variable) |
new spend data to check |
s_in_len * 320 bytes |
byte (variable) |
shielded output data to check |
s_out_len * 948 bytes |
byte (220) |
sighash |
220 bytes |
where
transparent data to check :
(Some of the below data is already sent in the inittx command, but sending it again is easier for checking purposes)
Type |
Content |
Expected |
byte (36) |
Prevout point |
|
byte (26) |
Script |
|
byte (8) |
Value |
u64 |
byte (4) |
Sequence number |
|
previous spend data to check :
Type |
Content |
Expected |
byte (32) |
Rseed of the spent note |
|
byte (8) |
Note position of spent note |
u64 |
new spend data to check:
NOTE: the values below should have used randomness from INS_GET_SPENDINFO if applicable
Type |
Content |
Expected |
byte (32) |
spend cv |
should have used rcv from ledger |
byte (32) |
Anchor |
|
byte (32) |
Nullifier |
should have used old note Rseed and note position |
byte (32) |
Rk |
should have used alpha from ledger |
byte (192) |
zkproof |
|
shielded output data to check:
Type |
Content |
Expected |
byte (32) |
output cv |
should have used rcv from ledger |
byte (32) |
note commitment |
should have used rseed from ledger |
byte (32) |
ephemeral key |
should have used rseed from ledger |
byte (580) |
enc_ciphertext |
ledger checks correct memo-type too |
byte (80) |
out_ciphertext |
|
byte (192) |
zkproof |
|
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xa3 |
P1 |
byte (1) |
Payload desc |
0 = init |
|
|
|
1 = add |
|
|
|
2 = last |
P2 |
byte (1) |
TxVersion |
4 = Sapling |
|
|
|
5 = NU5 |
L |
byte (1) |
Bytes in payload |
(depends) |
The first packet/chunk includes only the derivation path
All other packets/chunks contain data chunks that are described below
First Packet
Field |
Type |
Content |
Expected |
Other Chunks/Packets
Field |
Type |
Content |
Expected |
Data |
bytes... |
Message |
|
Data is defined as:
Field |
Type |
Content |
Expected |
Message |
bytes.. |
transaction_blob bytes as defined above |
|
Field |
Type |
Content |
Note |
hash |
byte (32) |
Hash of transaction_blob |
SHA256 |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Field |
Type |
Content |
Note |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
INS_EXTRACT_TRANSSIG
Returns a SECP256K1 signature for a sapling transparent input if available. Othrewise, it returns only an error code.
- This command requires that you already called INS_CHECKANDSIGN.
It gives the signatures in order of the transaction.
Returns error if all signatures are retrieved.
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xa5 |
P1 |
byte (1) |
Request User confirmation |
always 0 |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
!= 0 |
Field |
Type |
Content |
Note |
SECP256K1 |
byte (64) |
R/S signature |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Field |
Type |
Content |
Note |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
INS_EXTRACT_SPENDSIG
Returns a spend signature for a sapling shielded spend input if available. Othrewise, it returns only an error code.
- This command requires that you already called INS_CHECKANDSIGN.
Field |
Type |
Content |
Expected |
CLA |
byte (1) |
Application Identifier |
0x85 |
INS |
byte (1) |
Instruction ID |
0xa4 |
P1 |
byte (1) |
Request User confirmation |
No = 0 |
P2 |
byte (1) |
Parameter 2 |
ignored |
L |
byte (1) |
Bytes in payload |
0 (empty) |
Field |
Type |
Content |
Note |
RedJubjub signature |
byte (64) |
R/S signature |
|
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |
Field |
Type |
Content |
Note |
SW1-SW2 |
byte (2) |
Return code |
see list of return codes |