• Hash256
• Hash160
• Reverse Bytes
• Satoshis

Derivation Paths

How HD wallets derive keys.

The cool thing about extended keys is that they can derive children, and these child keys can derive more children, and so on. This allows you to create a tree of extended keys, with each key having its own unique derivation path from the master key.

You can derive keys in any way you want. But to help with compatibility between wallets, we have a set structure for how we derive keys for use in a hierarchical deterministic wallet.

The most common derivation paths used are:

• BIP 44: `m/44'/0'/0'` (for `1addresses`)
• BIP 49: `m/49'/0'/0'` (for `3addresses`)
• BIP 84: `m/84'/0'/0'` (for `bc1addresses`)

1. Notation

First of all, we have a basic notation for describing the derivation path for a specific extended key. For example:

``m/0/1/3'``

The slashes `/` indicate a new level in the tree (a new child). The numbers (e.g. `0`) indicate the child number from the parent.

The only other thing you need to know about the notation is that a `'` or `h` indicates a hardened child `extended private key` (which means that the public keys it creates cannot be derived by the `extended public key`):

• `0` - Normal Child (index `0`)
• `0'` - Hardened Child (index `2147483648`)

This `'` just saves us having to write the full index numbers for hardened children. For example, `3'` means index `2147483651`.

Tip: You can derive up to `4294967296` children from a single extended key. The first half are for normal children, and the second half are for hardened children.

Note: Deriving hardened children is the default. Normal children are only derived when it would be useful to have a corresponding extended public key for deriving the same public keys.

2. Wallet Structure

To help with consistency between wallets, BIP 44 introduced the following structure:

``m / purpose' / coin_type' / account' / change / index``
`m`: Master

The master key (created from a seed).

`m/44'`: Purpose (hardened)

This specifies the upcoming wallet structure.

There are three schemes currently being used by wallets:

Tip: The number reflects the number of the BIP. New schemes can use different BIP numbers.

`m/44'/0'`: Coin Type (hardened)

The cryptocurrency the keys will be used for.

Different cryptocurrencies can use the same `private keys` and `public keys` derived from a seed. So instead of having separate seeds for different currencies (or using the same public keys on different chains), we can use the same seed with different derivation paths instead.

``````0' = Bitcoin
1' = Bitcoin (Testnet)
2' = Litecoin
3' = Dogecoin
...``````

This is useful in hardware wallets, where you can have a single seed and use it for holding a variety of different coins.

`m/44'/0'/0'`: Account (hardened)

This allows you to create separate accounts for funds. The default account is `0'`.

For example, you can use the same seed yet still create separate “pots” for receiving payments. The coins in these separate accounts will never be mixed.

Tip: You could obviously create many different accounts at various indexes at this level. But to keep recovery simple, a wallet should create accounts in sequential order, and not create a new account if a previous one has not been used.

`m/44'/0'/0'/0`: Change

The keys and addresses we use are separated in to “Receiving” and “Change”.

• Receiving = `0` - Addresses that we will give out to people for receiving payments.
• Change = `1` - Addresses we use for sending change back to ourselves when we make transactions.

This means you will always be able to identify the coins that arrived from external payments.

`m/44'/0'/0'/0/0`: Index

These are the extended keys that you use for their `private keys` and `public keys` for actual usage in the wallet.

So as you can see, the first few levels in the path are just used to structure the hierarchical deterministic wallet in a practical way.

The actual keys used for addresses are in lowest level of the tree.

3. Derivation Paths

Here are some actual derivation paths used by wallets.

BIP 32: `m/0'/0/0`(deprecated)

This is the original derivation path specification in BIP 32.

It just used the first child for accounts, and the next two children below for separating external and internal addresses. The children of these are used for their actual `private keys` and `public keys` to create `addresses`.

``m / account' / external / index``

This is a nice and simple derivation path, but it doesn’t allow for the option of creating alternative derivation path schemes.

This is where BIP 44, BIP 49, and BIP 84 come in.

BIP 44: `m/44'/0'/0'/0/0`

BIP 44 builds upon the original BIP 32 scheme to include a purpose1 (which is like a version number to identify the upcoming scheme), as well as a coin type so that the same seed can be used to generate keys for different cryptocurrencies.

The `public keys` are encoded to `1addresses` (P2PKH).

BIP 49: `m/49'/0'/0'/0/0`

BIP 49 uses the same structure as BIP 44, but is used to indicate that the `public keys` should be encoded in to `3addresses` (P2WPKH-P2SH).

BIP 49 Serialization

The extended keys in the BIP 49 derivation path use the version bytes `049d7878` “yprv” or `049d7cb2` “ypub” during serialization. This allows you to identify an extended key when it is part of the BIP 49 scheme.

For example:

``yprvABrGsX5C9jant45o1Au7iHH54A8GXQH9SGhK5vkYKPUBDYsFy6KNUWX24moUE6KxoCh2qtZ8UpLaDWQiqt4aPdvvgjszQ4VrbLpfp5patGg``

BIP 84: `m/84'/0'/0'/0/0`

BIP 84 uses the same structure as BIP 44, but is used to indicate that the `public keys` should be encoded in to `bc1addresses` (P2WPKH).

BIP 84 Serialization

The extended keys in the BIP 84 derivation path use the version bytes `04b2430c` “zprv” or `04b24746` “zpub” during serialization. This allows you to identify an extended key when it is part of the BIP 84 scheme.

For example:

``zprvAWgYBBk7JR8GjMGuqXgjvNNaE8GiU2GeMPDXsKeRhPr4GegVDkUw6aBA5ym4DzytCqoqbN9gwUh86o2HZaUbBscXZ5aQyyKLs4tKCeThpsa``

4. Example

The following takes a seed (mnemonic sentence or hex) and derivation path, and shows you the `address` for the `private extended key` in that path (along with the next few children too).

Try it! - Derivation Paths

BIP 44: m / purpose’ / coin type’ / account’ / receving / index

``````m/44h/0h/0h/0/0: 1AZnveys2k5taGCCF743RtrWGwc58UMeq
m/44h/0h/0h/0/1: 1AMYJTJyV4o1hwNACJtfdXBW6BiD1f5FXb
m/44h/0h/0h/0/2: 1NPFFtSiFRatoeUf35rwYb8j8C1u7sVhGa
m/44h/0h/0h/0/3: 1L44VTYEzWesp8cxnXcPGbUzuwTYoSW9at
m/44h/0h/0h/0/4: 1FK85vpZavzZu6oBCvBcmD4FWXQT5fVYRu
m/44h/0h/0h/0/5: 12QaHfWLtyuMwNXuap3FscMY434bw4TS6n
m/44h/0h/0h/0/6: 1NeFG5BYAR9bnjAG72SDYKvNZBH4kPa8r1
m/44h/0h/0h/0/7: 1yF3BiHqbQKL4aRfNYHQt4ZpgNagC4nQe
m/44h/0h/0h/0/8: 144vmUhuAZJsV3m2GsP5Kqp55Pmzwx2gna
m/44h/0h/0h/0/9: 1DQM5w6C7gNaCKBxQV3rXKftcamRKDPQ2M
m/44h/0h/0h/0/10: 17XRvBac5xpgMVr6LbsDA56fgsaAed4oEV
m/44h/0h/0h/0/11: 1BSQC3Qn38UT2WVfcM6LdybkfE7tTGW5M2
m/44h/0h/0h/0/12: 1KUG4EDePnG97xQNXtuU9Xmp4sThqFvSoS
m/44h/0h/0h/0/13: 18sXnPcBnXBRFBYbqr85aKPPNpwT4f52a8
m/44h/0h/0h/0/14: 15S2gpAVvprN1GPE44oXCdtkA4L7yQtBkX
m/44h/0h/0h/0/15: 1FvC2STfbj7dcr2ApAPhagnSCP5Dmy79nH
m/44h/0h/0h/0/16: 15VZHWTEjnQuJSvUHzS7K6gmYjNv4A5cVJ
m/44h/0h/0h/0/17: 1N4S7Z43gb22PDCcpjHhX25cgDSLxegdWm
m/44h/0h/0h/0/18: 1MzS2BktGqokVM4kDuB6VavjLuib72W2je
m/44h/0h/0h/0/19: 1GDLeWJ4FcK2uiTFvLshtVcBArA7M9ECxq``````

Gap Limit: When recovering a wallet from a seed, you should only check the first 20 receiving addresses for a balance. If none have been used in the past, you can consider the account as unused.

Never enter your actual seed in to a website. Websites can save what you enter and use it to steal your coins.

5. Code

To save on code, these snippets use handy libraries (bitcoin-ruby, hdkeychain) for deriving extended keys.

Ruby

``````require 'bitcoin' # sum gem install bitcoin-ruby

# ------
# BIP 44
# ------
# Note: Hardened keys start at 2**31 (the second half of the 2**32 possible children).

m = Bitcoin::ExtKey.generate_master(seed.htb) # convert hex to binary
purpose   = m.derive(2**31+44) # m/44'
coin_type = m.derive(2**31+44).derive(2**31+0) # m/44'/0'
account   = m.derive(2**31+44).derive(2**31+0).derive(2**31+0) # m/44'/0'/0'
receiving = m.derive(2**31+44).derive(2**31+0).derive(2**31+0).derive(0) # m/44'/0'/0'/0

20.times do |i|
end``````

Go

``````package main

import (
"encoding/hex" // byte array to hex string
"fmt"

"github.com/btcsuite/btcd/chaincfg" // chaincfg.MainNetParams
"github.com/btcsuite/btcutil/hdkeychain" // https://godoc.org/github.com/btcsuite/btcutil/hdkeychain
)

func main() {

// From Seed
seed, _ := hex.DecodeString(seedhex) // hex to bytes
// fmt.Println("seed: ", seedhex)

// Generate Seed
// seed, _ := hdkeychain.GenerateSeed(uint8(16))
// fmt.Println(hex.EncodeToString(seed)) // bytes to hex

// ------
// BIP 44
// ------
// m
m, _ := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)

// m/44h
purpose, _ := m.Child(hdkeychain.HardenedKeyStart + 44)

// m/44h/0h
coin, _ := purpose.Child(hdkeychain.HardenedKeyStart + 0)

// m/44h/0h/0h
account, _ := coin.Child(hdkeychain.HardenedKeyStart + 0)

// m/44h/0h/0h/0
receiving, _ := account.Child(0) // 0 = receiving, 1 = change

// m/44h/0h/0h/0/*
for i := 0; i < 20; i++ {
index, _ := receiving.Child(uint32(i)) // takes an unsigned integer