This article is not intended for beginners in the crypto space. It is an in-depth analysis on the structure and usage of an HD Wallet for developers.
Hierarchical Deterministic Wallets (or HD wallets for short) were introduced by BIP 32 and later improved by BIP 44. BIPs (if you’re not familiar with them) stand for Bitcoin Improvement Proposals. While HD wallets were introduced by the Bitcoin community, it is a wallet structure that supports many coins. HD wallets can allow for an entire suite of crypto-wallets to be generated from a single seed phrase, although not a commonly used feature.
But what is an HD wallet? Put simply, an HD wallet is a public/private key tree all starting from a root node (master node). Here’s a great image for visualization:
An HD wallet tree is represented by derivation paths to the first address node. For example the default for Ethereum is m/44'/60'/0'/0. Each number in that path represents a certain level in the tree above.
m / purpose' / coin_type' / account' / chain / address_index
- 44 — BIP 44 Purpose
- 60 — Ethereum’s coin type
- 0 — Account 0
- 0 — Chain 0
For the most standard list of coin type codes look at this satoshilabs repo
Technically speaking, Hierarchical Deterministic Wallets are a tree structure where each node has an extended private and public key. Any node can have any number of children. Meaning a master key could regenerate 10 accounts in 10 different currencies each with a very high number of addresses. I chose 10 as an arbitrary number, the number could be as large as you’d like.
For example, a tree that holds the wallet keys for two networks (we can say Ethereum and Blackcoin) will have 2 children under the ‘purpose’ node which we’ll keep at 44. Such a tree might look like this:
It is important to note that the master private key’s sole purpose is wallet tree regeneration. It is unable to sign transactions. The HD wallet is designed to be able to generate many public/private key pairs from a single seed or mnemonic.
Tree level Breakdown
You can hold multiple unique currencies within the same HD Wallet by utilizing many coinType nodes instead of just one. The coinType codes are available in this satoshilabs repo.
The account node is used to hold multiple wallets for the same coin in a single master wallet. The account node would hold all the children addresses that belonged to that ‘account’. This is useful for situations where you may want to store money like you would in a bank, with a savings account or checking account or perhaps an account for your child or spouse and etc and etc.
Then we have the chain node, derived to a path of either 0 or 1. 0 is the external key pair chain, and is used for generating new public addresses. 1 is the internal keychain and is used for things like change addresses (in Bitcoin every transaction must have an address to send the excess funds to. The “change” of the transaction).
You might be wondering, “Why do we hold on to this node structure that is either irrelevant (these constructs don’t exist in other popular coins that utilize HD wallets) or unused (no one really uses the account functionality anymore)?” It’s because this is a derivation path that’s been formally agreed upon by the different crypto communities. This is significant because if I wanted to, I could create my own tree following any made up standard I want and create and sign valid transactions from the public/private keys. But could any other wallet ever regenerate that structure? What happens if my app goes off the market? The user’s money is locked into a completely arbitrary private/public key tree. Not the best situation to be in. Therefore, we hold on to these artifacts of the past because an extra derivation or two is a small price to pay for consensus.
The leaves of an HD wallet tree represent the address nodes. By formatting the public key of the address node an address can be created for a specific currency. For those unaware, most currencies follow the math set forth by Bitcoin when it comes to address generation. However, to distinguish between the address for Ethereum and for Bitcoin, different formatting tactics are used lest users send Bitcoin to an Ethereum address and therefore losing that money forever. A common misconception is that one can spend the funds associated to an address by using the master private key, however this is false. The only way to properly sign a transaction from an address is to use that address’s local private key (not it’s extended private key!)
We’ve discussed the things you can do with an HD Wallet and how to do them. Let’s talk about how you should set up your wallet.
Unless your currency and that currency’s community make use of accounts, (the Bitcoin currency supports accounts but the community does not utilize them) your wallet structure should look a little like a broom or a rebel support craft.
root -- 44 -- 0 -- 0 -- 0 -- 2
Ideally, every parent should have one child until you reach the chain node, at which point an unlimited number of children should be allowed. These children are the address nodes.
In order to create an address for your coinType currency, look up the instructions for that currency. The starting point will be the address node’s public key but there will be some differing methods based on the currency guidelines.
To construct a transaction, make sure you the address has currency associated with it and use the private key of the address node to sign. You are using the address node’s private key to sign a transaction spending money from the address node’s public key.