TeachMeBitcoin

P2TR Key Path - Full Taproot Execution

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

9. P2TR Key Path — Full Taproot Execution

Overview

Pay-to-Taproot (P2TR), defined in BIP 340/341/342 and activated in November 2021 (block 709,632), is Bitcoin's most advanced native script type. Taproot uses Schnorr signatures, Merkleized Abstract Syntax Trees (MAST), and key aggregation to dramatically improve privacy, efficiency, and expressiveness.

The key path spend is the simplest P2TR execution: a single Schnorr signature over a tweaked public key, indistinguishable from a simple single-signature spend regardless of the script complexity hidden in the Taproot tree.

Script Structure

Locking script (scriptPubKey) — 34 bytes:

OP_1 <32-byte x-only public key>

The OP_1 represents witness version 1. The 32-byte key is the "output key" — a tweaked version of the internal public key.

scriptSig: Empty.

Witness (key path):

01
<64-byte Schnorr signature>

Or with a non-default SIGHASH:

01
<65-byte Schnorr signature + SIGHASH byte>

Taproot Key Tweaking

The output key Q is derived by tweaking an internal key P with the Merkle root of the script tree:

Q = P + t·G

where:
  t = tagged_hash("TapTweak", P || merkle_root)
  G = secp256k1 generator point

If no scripts exist:
  t = tagged_hash("TapTweak", P)

This means the output key commits to the entire script tree. Spending via key path spends Q with a signature, revealing nothing about the scripts.

BIP 340 Schnorr Signatures

Schnorr signatures replace ECDSA in Taproot. A Schnorr signature is exactly 64 bytes:

Signature = (R, s)
  R: 32-byte x-coordinate of nonce point
  s: 32-byte scalar

Verification:
  s·G == R + tagged_hash("BIP0340/challenge", R || P || msg) · P

Advantages over ECDSA:
  - Linear: sig(a+b) = sig(a) + sig(b) → enables MuSig key aggregation
  - Non-malleable: Deterministic R via BIP 340
  - Batch verifiable: Multiple sigs verified together faster
  - Smaller: 64 bytes vs 71-72 bytes DER-encoded ECDSA

BIP 341 Signature Hash (Tapscript Sighash)

sighash_type options:
  0x00 = SIGHASH_DEFAULT (same as ALL, but omits type byte in signature)
  0x01 = SIGHASH_ALL
  0x02 = SIGHASH_NONE
  0x03 = SIGHASH_SINGLE
  0x81 = SIGHASH_ALL | ANYONECANPAY
  ...

Committed fields in Taproot sighash (BIP 341):
  - version, locktime
  - All outpoints (if not ANYONECANPAY)
  - All amounts of inputs (critical: all input values committed)
  - All scriptPubKeys of inputs
  - All sequences
  - All outputs (if SIGHASH_ALL)
  - spend_type (key path vs script path)
  - input_index

The commitment to all input amounts and all input scriptPubKeys prevents fee-manipulation attacks against hardware wallets, solving a long-standing issue.

Privacy Properties

A P2TR output looks identical on-chain whether it:
  - Is a simple single-sig wallet
  - Is a complex 5-of-9 multisig
  - Is a Lightning channel
  - Is a DLC contract
  - Has 100 script alternatives in its Tapscript tree

Key path spend: Reveals NOTHING about scripts. Just a 64-byte signature.
This is a revolutionary privacy improvement for Bitcoin.
☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!