Ledger Application Code in C++
Ledger Application
- Source code forks off the ledger-boilerplate project
- binary build
Source Code Explained
All Ledger transports must be sent with a byte prefix that defined what the payload type is. This is used to deserialize and display on the ledger device.
| Byte_Prefix | Enum | Description |
|---|---|---|
| 0x01 | SIGN_UTF8 | Sign UTF8 message for Mainnet |
| 0x02 | SIGN_TRANSACTION | Sign Transaction for Mainnet |
| 0x03 | SIGN_DIGEST | Sign the exact bytes provided in payload. Must be exactly 32 bytes like a sha256 hash |
| 0x0B | SIGN_UTF8_TESTNET | Sign UTF8 message for Testnet |
| 0x0C | SIGN_TRANSACTION_TESTNET | Sign Transaction for Testnet |
Please see for more information how Partisia Blockchain works:
Address Derived
Partisia HD addresses are derived as follows:
- Path
m/44'/3757'/0'/0/<idx>For Ledger
idxwill be 0 - The Private Key is derived from the HD Path, and the uncompressed Public Key is derived from the Private Key
- To keep compatibility we convert the 64 byte public key into 65 bytes by prefixing the public key with
0x04 - A sha256 hash is generated from the 65 bytes Public Key
- The first 20 bytes of the hash prepended by
0x00to create a 21 byte Partisia Address
Transactions Explained
In Partisia blockchain a valid transaction signature is defined by the following steps:
- A Chain Id is appended to the end of a transaction payload
Chain Id for Testnet is fixed at: [0, 0, 0, 27, 80, 97, 114, 116, 105, 115, 105, 97, 32, 66, 108, 111, 99, 107, 99, 104, 97, 105, 110, 32, 84, 101, 115, 116, 110, 101, 116] Chain Id for Mainnet is fixed at: [0, 0, 0, 19, 80, 97, 114, 116, 105, 115, 105, 97, 32, 66, 108, 111, 99, 107, 99, 104, 97, 105, 110]
- A sha256 hash is then generated from The transaction payload. This 32 byte hash is called the
digest - The private key is used to generate a canonical signature from the
digest - The Signature returned from the Ledger Device is in
DERformat. Theledger-mpc-appconverts it into Partisia Signature format below.
Partisia Signatures
Partisia Signature are always 65 bytes and defined as follows:
| Byte Range | Value |
|---|---|
| 0..1 | Recovery Param |
| 1..33 | R Value |
| 33..65 | S Value |
Deserializing
Depending on the byte prefix the device, the ledger is set to deserialize in the following ways
UTF8 Message
Byte prefix
0x01(mainnet) or0x0B(testnet)
The payload must contain valid UTF8 bytes form byte range [1..]
Digest Hash
Byte prefix
0x03
The payload must be 33 bytes exactly with the first byte being 0x03
Transaction Payload
Byte prefix
0x02(mainnet) or0x0C(testnet)
Transaction must be formatted as follows:
Inner
24 bytes following the transaction type prefix
| Byte Range | Value |
|---|---|
| 0..8 | nonce |
| 8..16 | validTo (date transaction is no expires |
| 16..24 | fee |
Header
25 bytes following the
Inner
| Byte Range | Value |
|---|---|
| 0..21 | contract |
| 21..25 | payload length |
Transaction Payload
unknown bytes following the
Header
| Byte Range | Value |
|---|---|
| 0.. | transaction payload |
Transaction MPC Transfer
There is a special check to see if the user is making a MPC transfer. If they are a more custom deserialization occurs and a more detailed display on the Ledger device is provided
Transaction Contract
For all other transactions, simply the Contract, fee, and payload are displayed
ledger-mpc-app
Partisia has developed a JS application that will interface with the Ledger App here:
Running the App
To run the app and test all the functionality of the Ledger Device please do the following:
git clone git@gitlab.com:partisiablockchainapplications/ledger-mpc-app.git
cd ledger-mpc-app
# install dependencies
npm i
# add your MNEMONIC into a .env file
echo MNEMONIC="word1 word2 word3 ..." >> .env
# unlock and open ledger to Partisia App
npm run test