Hierarchical determinism: how Bitcoin's HD wallets are born

Hierarchical determinism: how Bitcoin's HD wallets are born

Last updated: July 1, 2026
Contents
  1. Why HD wallets exist
  2. The wallet as a tree
  3. From extended keys to addresses
  4. Bringing it all together
  5. Wrapping up

In my explainer on mnemonic seeds, we explored how recovery phrases emerge from pure entropy - coin tosses, dice rolls, pure randomness. We learned how that randomness is encoded into a string of words: easier to memorise and backup than a really big number.

But that’s not the whole story. After generating a mnemonic, how does a wallet conjure up addresses? Why do those addresses always appear in the same order, every time? How does your seed phrase turn into extended keys, derivation paths, and the whole branching architecture of your wallet?

In this guide, we’ll explore the invention that underpins these questions: hierarchical deterministic (HD) wallets.

If you haven’t already, I recommend you start with my mnemonic article - the seed and passphrase you generate there will follow you into this guide.

Why HD wallets exist

Before HD wallets (BIP 32) and mnemonics (BIP 39), people relied on “JBOK” wallets, or “Just a Bunch of Keys”. Every private key was generated individually, lived alone, and had to be backed up separately.

HD wallets provide an elegant solution. They are:

  • Hierarchical: keys live in a tree structure
  • Deterministic: the same seed always regenerates the same tree

Modern wallets extract everything from a single 512-bit seed. That seed becomes a master extended private key, which becomes the root of your entire key tree:

🔑 Mnemonic Generator

Words:

Seed:

Master Extended Private Key:

Private Key Chain Code

Disclaimer: For demo purposes only. Do not use this mnemonic for storing Bitcoin, and never - under any circumstances - enter your real mnemonic into any website.

The master key - colour-coded above - is created by putting the seed through an HMAC function to generate another set of 64 bytes.

  • What is HMAC? Hash-based Message Authentication Code is a hashing method. It takes input data + a secret key and outputs fixed-length pseudo-random bytes. We use it repeatedly to “walk” down our wallet tree.
  • Why not use the seed directly? The seed and master key are both 64 bytes in length - why do we hash it again? Before BIP 39, seeds weren’t always 64 bytes. Passing it through HMAC is a (somewhat redundant) way to normalise everything.

The wallet as a tree

Your master extended private key sits at the trunk. It’s as sensitive as the seed itself: compromise it, and the entire wallet is gone. This is the key your hardware wallet hides from the world.

Each branch in the tree is created by feeding two things into HMAC:

  1. The current extended private key
  2. An index number

Each extended key can produce over 4 billion children, giving us huge, flexible space to build a hierarchy. A specific sequence of these branches is called a derivation path.

Let’s explore the many possible derivation paths of your wallet’s tree:

🔗 Wallet Derivation Explorer

purpose
coin
account
BIP-84 (Native SegWit)
Bitcoin
Account #0

Account-level path:

m/84'/0'/0'

Extended Public Key ():

Extended Private Key ():

Breaking down these first 3 levels:

  • Purpose: Defines the script type. For example, 84 refers to BIP84 (Native SegWit with P2WPKH addresses).
  • Coin: A single wallet seed can actually hold multiple cryptocurrencies. The number zero refers to the OG: Bitcoin.
  • Account: Does what it says on the tin, enabling segmentation for different purposes (personal, business, savings, whatever).

So for example, if you were setting up a Segwit (BIP 84) Bitcoin wallet, your derivation path might be: m/84'/0'/0'. If you decided to create an additional account, that new account would be found at m/84'/0'/1'.

From extended keys to addresses

These first layers yield your account-level extended keys: the xpub and xprv.

  • The xpub (Extended Public Key) is frequently the first key to be surfaced to users in wallet software. It can derive children, but only public keys. My open-source donation widget uses an xpub to derive all its addresses, for example.
  • The xprv (Extended Private Key) can derive everything - private keys, public keys, addresses. For obvious reasons, it is highly sensitive.

I’ve glossed over some complexities here. Curious readers can go on deeper technical tangents below, but these points aren’t essential for the rest of the guide.

Why do some xpubs start with ypub or zpub?

Wallet developers improvised “version bytes” (ypub, zpub) to indicate script types. It didn’t scale, and BIP86 (Taproot) went back to plain xpub. Modern practice is shifting toward Output Descriptors instead.

How can the xpub work without the xprv?

Thanks to the magic of elliptic-curve cryptography, an xpub can only derive public keys and addresses, whereas the xprv can derive both public and private keys (and can spend funds).

This opens up several useful patterns without risking exposure of your xprv. For example, you could create a “watch only” wallet using Sparrow to securely monitor your balances without requiring access to your hardware wallet (on which your xprv is stored). You could create a donation service that derives a fresh address every time money is received, increasing privacy versus a static address, all the while keeping your private keys securely offline.

Why the ’ symbol?

Apostrophes mark hardened children. Normal children can be derived from either the xprv or xpub. Hardened children require the xprv, meaning they enable creation of “secret” public keys. Each extended key can produce 4,294,967,296 child keys (~4.2 billion). The first half are the normal children, the second half, hardened children. The ' syntax saves on having to write full index numbers - /1' means 2,147,483,649 (or 2,147,483,648 plus one).

To unpack all the details, I suggest you let the brilliant Greg Walker learn you a bitcoin.

Now let’s finish the last two levels - the ones your wallet uses every day:

📍 Address Explorer

Addresses:

Generate a seed and select a derivation path to see addresses.

Script / Address Format:

BIP-44: P2PKH (Legacy) / Base58
BIP-49: P2WPKH-in-P2SH (Nested SegWit) / Base58
BIP-84: P2WPKH (Native SegWit) / Bech32
BIP-86: P2TR (Taproot) / Bech32m

At this depth:

  • Level 4 (0 or 1) - shown in pink
    • 0 = receiving addresses, shared for receiving funds
    • 1 = change addresses, used to receive change from transactions
  • Level 5 (0, 1, 2, 3…) - shown in yellow
    • The index increments each time you request a fresh address

At this point you’re working with simple keys, not extended ones. The address format (P2WPKH, P2TR, etc.) comes from the purpose field at level 1. A BIP86 purpose (i.e. Taproot, m/86') indicates that the wallet should generate P2TR addresses (starting with bc1p).

Address generation is another topic entirely - perhaps one for my next visual walkthrough.

Why not use a custom derivation path?

You could. It would work, in theory. You could derive addresses at some path known only to you - m/1337'/69'/1'/2/3, say - and thwart any would-be thieves who stumble upon your seed phrase.

In reality, though, using a custom derivation path can make it very difficult to recover your coins later on. Those looking to add extra security to their setup would do well to stick to a standard derivation path and instead investigate passphrases or multi-sig.

Can anyone tell if two addresses come from the same HD wallet?

No! This is one of the most fascinating things about HD wallets. They look beautifully structured on the inside, and like entropy soup from the outside.

This unlinkability is why it’s good practice to generate a fresh address for every transaction. To an outside observer, there is no way for them to tell whether the new address belongs to you (address index simply incremented by 1) or an unrelated third party.

Prefer RSS? Subscribe to the feed

Bringing it all together

Between this article and the previous one, you’ve gone from pure randomness, to a mnemonic, to a seed, to extended keys, to child keys, to real Bitcoin addresses capable of receiving funds.

And here’s the part which (to me) feels like science-fiction: you could do every step of this offline, and it would still work perfectly.

Paper and dice. No computer. No website or permission needed.

If you meticulously worked through these steps yourself to generate an address, it could receive millions of dollars’ worth of bitcoin in minutes, even if no computer on Earth has ever seen it before. It isn’t registered anywhere. Nobody “issues” it to you. There is no approval list, no form to fill in, no gatekeeper. The keys are yours, and yours alone.

Your address - which is ultimately just an expression of a really big number - could be carved into a stone tablet, or communicated to the outside world via shortwave radio, and anyone in the world would be able to transmit value to it. That is the magic of bitcoin. It’s just mathematics.

Take a step back and appreciate the journey you’ve taken:

🛤️ Wallet Journey Explorer

Binary Entropy:

BIP-39 Mnemonic:

PBKDF2

Wallet Seed:

HMAC

Master Extended Private Key:

Private Key Chain Code
HMAC

Address #0

Wrapping up

HD wallets are a quiet miracle of Bitcoin UX. They give us:

  • A single seed phrase that regenerates an entire wallet structure
  • Organised accounts without juggling dozens of keys
  • Recoverability across different devices, manufacturers, and software
  • Privacy without complexity

I’ve tried to do the topic justice here. While remarkably elegant, there’s a lot of technical depth to this subject that I wanted to cover properly. For the next article in this series, I’d like to explore address formats: P2PKH vs P2SH vs P2WPKH vs P2TR, how they work and what they reveal.

If you’d like to support development of this series, and of this website in general, you can send me bitcoin using the addresses below:

Your support is hugely appreciated, and will fund my coffee addiction.

Thanks for reading!