P2TR Key Path - Full Taproot Execution
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.
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: