A step-by-step guide on how mnemonic works (specifically on Cardano using cardano-cli
and cardano-wallet
), from deriving keys to using the address and signing transactions
TABLE OF CONTENT
- Guide on Mnemonic / Seed Phrase, Keys, and Addresses on Cardano
- Go to IOHK - Cardano Node repository on Github
- Scroll down to Executables, and download the binaries for your specific OS (MacOS, Linux, or Windows). For this demonstration, we're using node version 1.35.3
- Extract and copy the files to
~/.local/bin-cardano/node-1.35.3/
- Go to IOHK - Cardano Wallet repository on Github
- Download the binaries for your OS (MacOS, Linux, or Windows)
- Extract and copy the files to
~/.local/bin-cardano/wallet-v2022-08-16/
- Edit
~/.zshrc
or~/.bashrc
- Insert this
PATH
at the bottom... # Path for cardano-node, cardano-cli, and cardano-wallet export PATH="$HOME/.local/bin-cardano/wallet-v2022-08-16:$PATH" export PATH="$HOME/.local/bin-cardano/node-1.35.3:$PATH"
Note: there's some reduncancy with some files, such as
cardano-node
andcardano-cli
exist in both directories. The order ofPATH
declaration will determine which file will be used. In this case, the environment will use thecardano-node
directory for redundant files.
- Open new terminal session
- Check the version for each command
$ cardano-node --version # cardano-node 1.35.3 - darwin-x86_64 - ghc-8.10 # git rev 950c4e222086fed5ca53564e642434ce9307b0b9 $ cardano-cli --version # cardano-cli 1.35.3 - darwin-x86_64 - ghc-8.10 # git rev 950c4e222086fed5ca53564e642434ce9307b0b9 $ cardano-wallet version # v2022-08-16 (git revision: afe575663a866c612b4a4dc3a90a8a700e387a86)
Note: for Mac users, if you encounter any Security issues, open Apple > System Preferences > Security & Privacy, and click 'Allow' when prompted
To put it simply, mnemonic or seed phrase is a random number used for your private key represented in a human readable words. These words are specified in the BIP39 wordlist
-
Generate 24 seed phrase using. This is done locally and doesn't require internet connection
$ cardano-wallet recovery-phrase generate --size 24 | tee mnemonic.txt
Note:
tee
command means write the output into this file, while also echo the output into the terminal -
Convert the seed phrase into Master Root Key
$ cardano-wallet key from-recovery-phrase Shelley < mnemonic.txt | tee keys/root.xprv
Cardano uses Hierarchical Deterministic Wallet, and further standardized in CIP-1852. Cardano adapt the BIP32 standard in Bitcoin, but it's modified to accomodate Ed25519
For Cardano, the derivation path would be:
m / 1852' / 1815' / account' / role / index
Description:
m
: Root Master Key1852'
: Purpose → taken from the year of death of Ada Lovelace1815'
: Coin type → taken from the year of birth of Ada Lovelaceaccount'
: 0 .. 23 → number of accounts (explained later)role
:0
to indicate an address on the external chain, that is, an address that is meant to be public and communicated to other users1
to indicate an address on the internal chain, that is, an address that is meant for change, generated by a wallet software2
to indicate a reward account address, used for delegation
index
:0
if therole
is2
- Anything between 0 and 223 otherwise
One seed phrase can generate many accounts and use them seperately.
When using Eternl wallet, you can see the HD Wallets deriviation path on each account; (m/1852'/1815'/0'), (m/1852'/1815'/1'), and (m/1852'/1815'/2')
Steps to create these accounts:
- Derive a key from the MasterKey (
root.xprv
) to create anExtendedPrivateKey
for Account#0$ cardano-wallet key child 1852H/1815H/0H < keys/root.xprv | tee keys/account0.xprv
- Create the
ExtendedPublicKey
using the Account#0ExtendedPrivateKey
$ cardano-wallet key public --with-chain-code < keys/account0.xprv | tee keys/account0.xpub
- Repeat the step if you want to create additional accounts, e.g
1852H/1815H/1H
,1852H/1815H/2H
, and so on
Every account have their own set of addresses. An address is nothing more than a hashed public keys. In Shelley Era, an address consist of 2 different public key, a payment key and a stake key. As specified in CIP-1852, we will derive those 2 keys from the ExtendedPrivateKey
of Account#0
Payment key
- The full derivation path from the MasterKey would be
m / 1852' / 1815' / 0' / 0 / 0
-
The last two number defines
role
andindex
, as already explained previously -
Since we've already derived Account#0, we just need derive it further with
0/0
$ cardano-wallet key child 0/0 < keys/root.xprv | tee keys/account0_idx0.xprv
-
If you want to create another payment key, repeat the process with increment for the last value, like so
0/1
,0/2
,0/3
, and so on.
Stake key
- The full derivation path from the MasterKey would be
m / 1852' / 1815' / 0' / 2 / 0
-
The last two number defines
role
andindex
, as already explained previously -
Note that there's only 1 stake key for each account, so the
index
will always be0
-
Derive the key like we did in payment key
$ cardano-wallet key child 2/0 < keys/account0.xprv | tee keys/stake0.xprv
Note: we've only created the
ExtendedPrivateKey
for both payment and stake key, and notExtendedPublicKey
that we've done previously. This is because we will convert the payment and stake key private keys into Shelley compatible format first, and then we can create the public key in Shelley format. Shelley format is needed to create addresses, build transaction, and submit transaction usingcardano-cli
.
So far, we've created private keys for MasterKey, Account#0, payment, and stake keys.
# Master
root_xsk1wzh4vuzxn9s9hyq4v2jguxtmgry8ysfqnypmyup0wll3jh8ltdgm7pjfxxm8x6flan8zzewhqm57p6hzkc5uh65ky59ldl68ag38kt6l8mcdx2xn504v3h9w3ern0re6s8d5tkz7628077v8y8zv08ekps9nmhm5
# Account#0
acct_xsk1wzgkw0r9wsm70d2k9ddc340yak0l66523ngfmfe2qufscmlltdg48dvruejkc67gvr5rtfdvg54v758j52a69465n5m6u579ysu3pgm4tjjdta3g0y97pljj26qez4cxjn67wzc53stvpw372z6wpmn2y55a9l7d
# Payment
addr_xsk1cz5cuxguhmrgmrq0s7s8eghedmsw59l0uffqyemvngl66ahltdg74r2p6peg0u2dw93pwqlm2mjdhwduyn6k55yq6rv2cazfc92ltlkm8xpdkuaskdmd2ea6yl0admputnl3h5k7estgh3ps7ldhy5uqjcn5lrsa
# Stake
stake_xsk10prhunyw2paf32pq60le6f2setqhgjqxpxxch90dv42057hltdgmk0wkpdpjkkw5puf9358xj8ppk4qrdar0q4ahsecpmsnvjlywknx5r8hs2pcdhjudyx3hpvd3skx93akn6m3j0xpp6f5w72whqv8qaueg6v7s
Before we can create addresses, signing transaction, or doing anything with cardano-cli
, we need to convert these keys into a Shelley compatible format.
Note: for the next section,
ExtendedPrivateKey
andExtendedSigningKey
are actually the same thing in terms of underlying principle, same goes withExtendedPublicKey
andExtendedVerifyKey
. I use the name seperately just to differentiate between the Shelley format and the regular or bech32 format.
For this section, we will do the following:
- Convert Payment Key into Shelley format
- Convert Stake Key into Shelley format
- Create a public key for Payment Key using the Payment Key that has been converted into Shelley format
- Create a public key for Stake Key using the Stake Key that has been converted into Shelley format
Step:
-
Convert
payment0_idx0.xprv
intopayment0_idx0.xskey
$ cardano-cli key convert-cardano-address-key \ --shelley-payment-key \ --signing-key-file keys/payment0_idx0.xprv \ --out-file keys/payment0_idx0.xskey
This will create
ExtendedSigningKey
, which is a payment key in Shelley format -
Convert
stake0.xprv
intostake0.xskey
$ cardano-cli key convert-cardano-address-key \ --shelley-stake-key \ --signing-key-file keys/stake0.xprv \ --out-file keys/stake0.xskey
This will create
ExtendedSigningKey
for the stake key in Shelley format
After we convert the ExtendedPrivateKey
into ExtendedSigningKey
, we can then create the ExtendedPublicKey
into a Shelley format ExtendedVerifyKey
-
Generate the verify key from
payment0_idx0.xskey
$ cardano-cli key verification-key \ --signing-key-file keys/payment0_idx0.xskey \ --verification-key-file keys/payment0_idx0.xvkey
-
Generate the verify key from
stake0.xskey
$ cardano-cli key verification-key \ --signing-key-file keys/stake0.xskey \ --verification-key-file keys/stake0.xvkey
Done! We have completed the steps on deriving keys necessary for later uses, such as creating addresses and signing transactions.
Before we continue, we need to convert the ExtendedVerifyKey
into a shortened key version VerifyKey
-
Shorten the
payment0_idx0.xskey
intopayment0_idx0.vkey
$ cardano-cli key non-extended-key \ --extended-verification-key-file keys/payment0_idx0.xvkey \ --verification-key-file keys/payment0_idx0.vkey
-
Shorten the
stake0.xskey
intostake0.vkey
$ cardano-cli key non-extended-key \ --extended-verification-key-file keys/stake0.xvkey \ --verification-key-file keys/stake0.vkey
Now we can create the addresses using both VerifyKey
for the Payment and Stake key
It's fairly simple and easy to build addresses when we have those two VerifyKey
prepared. As of now, there are 3 testnet: Legacy, Preview, and Preprod. The legacy testnet will be deprecated, and now we will use the Preprod. We use this because Cardanoscan Testnet is using the Preprod version of testnet. From this Getting Started Testnet doc, we will use INTEGER: 2
for the testnet magic number.
- Build the address
cardano-cli address build \ --payment-verification-key-file keys/payment0_idx0.vkey \ --stake-verification-key-file keys/stake0.vkey \ --testnet-magic 2 \ --out-file addresses/account0_idx0.addr
- The prefix for testnet is
addr_test
.
Basically the same with the previous Testnet address, just replace the --testnet-magic
with --mainnet
- Build the address
cardano-cli address build \ --payment-verification-key-file keys/payment0_idx0.vkey \ --stake-verification-key-file keys/stake0.vkey \ --testnet-magic 2 \ --out-file addresses/account0_idx0.addr
- The prefix for mainnet is
addr
Done!
Congratulations, you've created your own Cardano address from scratch using cardano-wallet
and cardano-cli