P2PK Script - Full Anatomy and Execution
1. P2PK Script — Full Anatomy and Execution
Overview
Pay-to-Public-Key (P2PK) is the oldest and simplest locking script in Bitcoin. It was used extensively in the earliest blocks, including Satoshi's coinbase transactions in 2009. Unlike later script types, P2PK locks funds directly to a raw public key rather than a hashed address. This design is both elegant and historically significant, though it has been largely superseded by P2PKH due to privacy and security improvements.
Script Structure
A P2PK locking script (scriptPubKey) takes the following form:
<pubkey> OP_CHECKSIG
Where <pubkey> is a 65-byte uncompressed public key (prefix 0x04) or a 33-byte compressed public key (prefix 0x02 or 0x03). The corresponding unlocking script (scriptSig) is simply:
<signature>
That is the entire spending mechanism — a single DER-encoded signature pushed onto the stack.
Byte-Level Anatomy
For an uncompressed key, the full locking script in hex resembles:
41 <- push 65 bytes
04
<32-byte X coordinate>
<32-byte Y coordinate>
AC <- OP_CHECKSIG
For a compressed key:
21 <- push 33 bytes
02 or 03
<32-byte X coordinate>
AC <- OP_CHECKSIG
The unlocking script pushes a DER-encoded signature followed by a 1-byte SIGHASH flag:
47 or 48 <- push 71 or 72 bytes
<DER-encoded signature>
01 <- SIGHASH_ALL flag
Execution Walkthrough
Script execution in Bitcoin works as a stack machine. To validate a P2PK spend, the interpreter concatenates the scriptSig and scriptPubKey and executes them sequentially.
Step 1: Execute scriptSig
Stack before: []
Instruction: PUSH <signature>
Stack after: [<sig>]
Step 2: Execute scriptPubKey — push public key
Stack before: [<sig>]
Instruction: PUSH <pubkey>
Stack after: [<sig>, <pubkey>]
Step 3: Execute OP_CHECKSIG
Stack before: [<sig>, <pubkey>]
Instruction: OP_CHECKSIG
- Pops pubkey and sig from stack
- Serializes the transaction according to the SIGHASH type
- Computes double-SHA256 of the serialized tx
- Verifies ECDSA signature over the hash
Stack after: [1] (success) or [0] (failure)
Step 4: Validation check
Stack final: [1]
Result: Non-empty, non-zero top element → VALID spend
Signature Hash Types
The SIGHASH byte at the end of the signature controls which parts of the transaction are committed to:
SIGHASH_ALL = 0x01 <- commits to all inputs and outputs
SIGHASH_NONE = 0x02 <- commits to inputs only, outputs flexible
SIGHASH_SINGLE = 0x03 <- commits to corresponding output only
SIGHASH_ANYONECANPAY modifier = 0x80 <- only current input is committed
Security Considerations
P2PK exposes the full public key on-chain at the time the UTXO is created (in the locking script). This means:
-
Quantum vulnerability window: If large-scale quantum computers become viable, an attacker could derive the private key from the exposed public key before it's spent. P2PKH only reveals the public key at spend time, providing a smaller window.
-
No address abstraction: The raw public key serves as the "address," which is unwieldy for humans to communicate.
-
No checksum: Unlike Base58Check addresses, raw public keys have no built-in error detection.
Despite these issues, P2PK outputs remain spendable and still exist in the UTXO set from early Bitcoin history. Nodes recognize and validate them correctly to this day.
Example: Satoshi's Genesis Block
The coinbase of block 0 (the genesis block) uses a P2PK output paying to a 65-byte uncompressed public key:
scriptPubKey (hex):
4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61d
eb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
ac
Decoded:
PUSH 65 bytes [04 67 8a fd b0 ... 1d 5f]
OP_CHECKSIG
This output has never been spent.
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: