Menu
BIP-bip-84 Final

BIP-84: Native SegWit Derivation

Derivation scheme for Native SegWit (P2WPKH) addresses. Standard path for bc1q addresses.

Type Bitcoin Improvement Proposal
Number bip-84
Status Final
Authors Pavol Rusnak
Original https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki
Requires

BIP-84: Derivation Scheme for P2WPKH

BIP-84 defines the standard derivation path for Native SegWit (P2WPKH) addresses, producing addresses that start with bc1q.

Purpose

Before BIP-84:

  • BIP-44 defined m/44'/0'/... for legacy addresses
  • BIP-49 defined m/49'/0'/... for wrapped SegWit (P2SH-P2WPKH)

BIP-84 extends this:

  • m/84'/0'/... for native SegWit (P2WPKH)

This allows wallets to:

  • Manage multiple address types from one seed
  • Know which address type to generate from the path
  • Maintain compatibility with existing HD infrastructure

Derivation Path

m / 84' / coin_type' / account' / change / address_index
LevelHardenedValueDescription
PurposeYes84’BIP-84 (native SegWit)
Coin TypeYes0’Bitcoin mainnet
AccountYes0’ to n’User accounts
ChangeNo0 or 10 = receiving, 1 = change
Address IndexNo0 to nSequential addresses

Example Paths

m/84'/0'/0'/0/0   First receiving address, account 0
m/84'/0'/0'/0/1   Second receiving address, account 0
m/84'/0'/0'/1/0   First change address, account 0
m/84'/0'/1'/0/0   First receiving address, account 1

Extended Key Versions

BIP-84 introduces new version bytes for serialized extended keys:

NetworkKey TypeVersionPrefix
MainnetPrivate0x04b2430czprv
MainnetPublic0x04b24746zpub
TestnetPrivate0x045f18bcvprv
TestnetPublic0x045f1cf6vpub

This allows wallets to distinguish SegWit extended keys from legacy.

Address Generation

From derived public key to P2WPKH address:

Public Key (33 bytes, compressed)

SHA256

RIPEMD160

Witness Program (20 bytes)

Bech32 Encode (witness version 0)

bc1q... address

Implementation

const bitcoin = require('bitcoinjs-lib');
const { BIP32Factory } = require('bip32');
const ecc = require('tiny-secp256k1');
const bip39 = require('bip39');

const bip32 = BIP32Factory(ecc);

// From mnemonic to seed
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
const seed = bip39.mnemonicToSeedSync(mnemonic);

// Derive BIP-84 account
const root = bip32.fromSeed(seed);
const account = root.derivePath("m/84'/0'/0'");

// Generate receiving addresses
for (let i = 0; i < 5; i++) {
  const child = account.derivePath(`0/${i}`);
  const { address } = bitcoin.payments.p2wpkh({
    pubkey: child.publicKey,
    network: bitcoin.networks.bitcoin
  });
  console.log(`m/84'/0'/0'/0/${i}: ${address}`);
}

Output:

m/84'/0'/0'/0/0: bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu
m/84'/0'/0'/0/1: bc1qnjg0jd8228aq7ez7e7n38hvkmjm8wqh6ek4zv3
m/84'/0'/0'/0/2: bc1qp59yckz4ae5c4efgw2s5njs68r8dp6k2xzqpjk
m/84'/0'/0'/0/3: bc1qgl5vlg0zdl7yvprgxj9fevsc6q6x5dmcyk3cn3
m/84'/0'/0'/0/4: bc1qm97vqzgj934vnaq9s53ynkyf9dgr05rargr04n

Python Implementation

from bip_utils import Bip39SeedGenerator, Bip84, Bip84Coins

# Generate seed from mnemonic
mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
seed = Bip39SeedGenerator(mnemonic).Generate()

# Create BIP-84 wallet
bip84_ctx = Bip84.FromSeed(seed, Bip84Coins.BITCOIN)
account = bip84_ctx.Purpose().Coin().Account(0)

# Generate addresses
for i in range(5):
    addr = account.Change(0).AddressIndex(i)
    print(f"m/84'/0'/0'/0/{i}: {addr.PublicKey().ToAddress()}")

Extended Public Key (zpub)

The zpub at account level enables watch-only wallets:

// Export zpub
const zpub = account.neutered().toBase58();
// zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs

// Import zpub for watch-only
const watchOnly = bip32.fromBase58(zpub);
const address = bitcoin.payments.p2wpkh({
  pubkey: watchOnly.derivePath('0/0').publicKey
}).address;

Comparison with Other BIPs

BIPPurposePathAddress PrefixOutput Type
44Legacym/44’/0’/…1…P2PKH
49Wrapped SegWitm/49’/0’/…3…P2SH-P2WPKH
84Native SegWitm/84’/0’/…bc1q…P2WPKH
86Taprootm/86’/0’/…bc1p…P2TR

Fee Savings

Native SegWit (BIP-84) provides significant fee savings:

Transaction TypeVirtual SizeSavings vs Legacy
P2PKH (legacy)~226 vBbaseline
P2SH-P2WPKH (BIP-49)~167 vB~26%
P2WPKH (BIP-84)~141 vB~38%

Test Vector

Mnemonic:

abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
PathAddress
m/84’/0’/0’/0/0bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu
m/84’/0’/0’/0/1bc1qnjg0jd8228aq7ece2l8nh6acv5v62d9d5qujka
m/84’/0’/0’/1/0bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el

Account xpub:

zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs

Agent Recommendations

  1. Use BIP-84 as default for new wallets
  2. Generate zpub for watch-only monitoring
  3. Implement gap limit (20 addresses)
  4. Support address reuse detection for privacy
  5. Consider BIP-86 (Taproot) for newer deployments
  • BIP-32: HD wallet derivation
  • BIP-39: Mnemonic seeds
  • BIP-43: Purpose field definition
  • BIP-44: Multi-account hierarchy
  • BIP-141: SegWit consensus rules
  • BIP-173: Bech32 addresses

Machine-Readable Summary

{
  "bip": 84,
  "title": "Derivation Scheme for P2WPKH",
  "status": "final",
  "purpose_value": 84,
  "path_template": "m/84'/coin'/account'/change/index",
  "address_type": "P2WPKH",
  "address_prefix": "bc1q",
  "extended_key_prefixes": {
    "mainnet_private": "zprv",
    "mainnet_public": "zpub",
    "testnet_private": "vprv",
    "testnet_public": "vpub"
  }
}