B++ Logo

Taproot

Taproot is a major Bitcoin protocol upgrade activated in November 2021 (block 709,632). It combines Schnorr signatures with MAST (Merkle Abstract Syntax Trees) to provide better privacy, efficiency, and flexibility for Bitcoin transactions. Pieter Wuille was a key designer (BIPs 340, 341, 342). Taproot introduces a new output type (P2TR) that enables:

  • Schnorr signatures: More efficient than ECDSA, enables signature aggregation
  • MAST: Hides unused script conditions in a Merkle tree
  • Better privacy: Complex contracts look identical to simple payments
  • Lower fees: Smaller transaction sizes for complex scripts
  • Key path spending: Simple single-signature spends look normal

Key Components

1. Schnorr Signatures (BIP 340)

Schnorr signatures replace ECDSA for Taproot outputs:

Benefits:

  • Linear: Enables signature aggregation (MuSig)
  • Smaller: 64 bytes vs 71-72 bytes for ECDSA
  • Batch verification: Verify multiple signatures faster
  • Proven security: Simpler mathematics, better understood

2. MAST (Merkle Abstract Syntax Trees)

MAST allows multiple spending conditions while only revealing the one used:

Complex Contract:
├── Condition 1: 2-of-3 multisig
├── Condition 2: Timelock + signature
├── Condition 3: Hash preimage reveal
└── Condition 4: Simple signature (key path)

When spending:
- Use Condition 4 → Looks like simple payment
- Use Condition 1 → Only reveal that condition
- Other conditions remain hidden in Merkle tree

3. Taproot Outputs (P2TR)

Addresses start with bc1p and use Bech32m encoding:

Format: bc1p + 32 characters
Example: bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac36sfj9ugtg7etq5

How Taproot Works

Key Path vs. Script Path

Taproot outputs can be spent in two ways:

Key Path (Simple Spend)

Output: P2TR address
Spend: Single Schnorr signature
Result: Looks identical to any other Taproot spend
Privacy: Maximum (no script revealed)

Script Path (Complex Spend)

Output: P2TR address (with hidden script tree)
Spend: Reveal one script branch + proof
Result: Reveals only the used condition
Privacy: Good (other conditions hidden)

Taproot Construction

1. Create internal key (from private key)
2. Create script tree (if needed)
3. Compute taproot output key:
   - If script tree: tweak internal key with script root
   - If key path only: use internal key directly
4. Generate P2TR address from output key

Code Examples

Creating a Taproot Address

Creating a MAST Script Tree


Privacy Benefits

Before Taproot

Multisig Transaction:
- Reveals all public keys
- Reveals all signatures
- Obvious it's a multisig
- Linkable to other multisig transactions

After Taproot

Multisig Transaction (key path):
- Looks identical to single-sig
- No script revealed
- No way to tell it's multisig
- Maximum privacy

Script Path Privacy

Even when using script path:

Complex Contract with 10 conditions:
- Only reveals 1 used condition
- Other 9 conditions hidden in Merkle tree
- Much better than revealing all conditions

Efficiency Benefits

Signature Size

ECDSA (SegWit):
- Signature: 71-72 bytes
- Public key: 33 bytes
- Total: ~104-105 bytes

Schnorr (Taproot):
- Signature: 64 bytes
- Public key: 32 bytes (x-only)
- Total: 96 bytes
- Savings: ~8-9 bytes per input

Transaction Size

For a 2-of-3 multisig:

Before Taproot (P2WSH):
- Script: ~105 bytes
- 2 signatures: ~142 bytes
- Total: ~247 bytes

After Taproot (key path):
- 1 signature: 64 bytes
- Total: 64 bytes
- Savings: ~74%!

MuSig (Multi-Signature Aggregation)

Taproot enables MuSig, where multiple signatures are combined into one:

Traditional Multisig:
- Key 1 signature: 71 bytes
- Key 2 signature: 71 bytes
- Key 3 signature: 71 bytes
- Total: 213 bytes

MuSig (Taproot):
- Aggregated signature: 64 bytes
- Savings: 70%!

Adoption

Current Usage

As of 2024:

  • ~5-10% of transactions use Taproot
  • Growing adoption in modern wallets
  • Required for advanced smart contracts

Migration

  1. Use P2TR addresses for new outputs
  2. Support Taproot in wallet software
  3. Migrate existing funds to Taproot for better privacy

Technical Details

Bech32m Encoding

Taproot uses Bech32m (modified Bech32) instead of Bech32:

  • Bech32: Used for SegWit (P2WPKH, P2WSH)
  • Bech32m: Used for Taproot (P2TR)
  • Difference: Constant in checksum calculation

Taproot Version

Taproot uses witness version 1:

Witness Program:
├── Version (1 byte): 0x01
└── Program (32 bytes): Taproot output key

Tapscript

Taproot introduces Tapscript, a new scripting language:

  • Based on Bitcoin Script
  • New opcodes: OP_CHECKSIGADD
  • Resource limits similar to SegWit


Resources