B++ Logo

Address Generation & Validation

Bitcoin addresses are human-readable encodings of output scripts. Understanding how to generate, validate, and work with different address types is fundamental to Bitcoin development.

Address Types Overview

Legacy Addresses (P2PKH)

Format: Starts with 1 (mainnet) or m/n (testnet)

1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2

Script: Pay-to-Public-Key-Hash

OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG

Script Hash Addresses (P2SH)

Format: Starts with 3 (mainnet) or 2 (testnet)

3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy

Script: Pay-to-Script-Hash (can contain any script)

OP_HASH160 <script_hash> OP_EQUAL

Native SegWit (P2WPKH)

Format: Starts with bc1q (mainnet) or tb1q (testnet)

bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq

Script: Pay-to-Witness-Public-Key-Hash

OP_0 <20-byte-pubkey-hash>

Native SegWit Script (P2WSH)

Format: Starts with bc1q but longer (mainnet)

bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3

Script: Pay-to-Witness-Script-Hash

OP_0 <32-byte-script-hash>

Taproot (P2TR)

Format: Starts with bc1p (mainnet) or tb1p (testnet)

bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297

Script: Pay-to-Taproot

OP_1 <32-byte-x-only-pubkey>

Address Comparison

TypePrefixSizeEncodingFee Efficiency
P2PKH125 bytesBase58CheckLowest
P2SH323 bytesBase58CheckLow
P2WPKHbc1q22 bytesBech32High
P2WSHbc1q34 bytesBech32Medium
P2TRbc1p34 bytesBech32mHighest

Generating Addresses

From Public Key to P2WPKH (Native SegWit)


Validating Addresses


Bech32 Encoding Details

Bech32 vs Bech32m

Bech32 (BIP-173):
- Used for SegWit v0 (P2WPKH, P2WSH)
- Checksum constant: 1

Bech32m (BIP-350):
- Used for SegWit v1+ (Taproot)
- Checksum constant: 0x2bc830a3

Why Bech32m?

Bech32 had a weakness where certain error patterns could go undetected. Bech32m fixes this for future witness versions.


From Script to Address


Address Derivation Paths

BIP Standards

BIPPathAddress TypeExample
BIP44m/44'/0'/0'P2PKH1...
BIP49m/49'/0'/0'P2SH-P2WPKH3...
BIP84m/84'/0'/0'P2WPKHbc1q...
BIP86m/86'/0'/0'P2TRbc1p...

Deriving Addresses from Seed


Multi-Signature Addresses

Creating 2-of-3 Multisig


Common Mistakes

Address Validation Pitfalls

  • BAD: Only checking prefix (address.startsWith('bc1'))
  • GOOD: Full validation with checksum verification using library functions

Network Mismatch

Always use consistent network parameters. Never mix mainnet keys with testnet addresses.

Checksum Errors

Always validate checksums before using an address - all libraries provide validation functions.


Best Practices

Address Generation

  1. Use Established Libraries: Don't implement encoding yourself
  2. Validate After Generation: Always verify the generated address
  3. Use Appropriate Types: Prefer SegWit/Taproot for lower fees
  4. Test on Testnet: Verify address generation works correctly

Address Handling

  1. Case Sensitivity: Bech32 is case-insensitive, Base58 is case-sensitive
  2. Display Formatting: Consider QR codes for long addresses
  3. Copy Protection: Use checksums to detect copy errors
  4. Network Verification: Always verify mainnet vs testnet

Security

  1. Never Reuse Addresses: Generate new addresses for each transaction
  2. Verify Derivation Paths: Ensure consistent paths across wallet imports
  3. Backup Seeds: Addresses can be regenerated from seeds

Summary

Understanding Bitcoin addresses requires knowledge of:

  • Encoding Schemes: Base58Check, Bech32, Bech32m
  • Script Types: P2PKH, P2SH, P2WPKH, P2WSH, P2TR
  • Derivation: BIP32/39/44/49/84/86 standards
  • Validation: Checksum verification and format checking

Modern applications should default to Bech32m (Taproot) addresses for the best fee efficiency and privacy features.