Thirteen days after the Genesis Block, something changed. In Block 728, mined on January 16, 2009, a transaction appeared with a scriptPubKey that looked nothing like the P2PK outputs that had preceded it. Instead of pushing a 65-byte public key followed by OP_CHECKSIG, the output contained five opcodes and only twenty bytes of key material:
OP_DUP OP_HASH160 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG
This was P2PKH—Pay to Public Key Hash—and it would become the dominant transaction type for the next eight years, producing the familiar addresses that begin with 1 and defining what most people think of when they hear "a Bitcoin address."
The innovation was deceptively simple: instead of embedding the public key directly in the output, hash it first. Store only the 20-byte hash. Require the spender to provide the original public key—along with a valid signature—when claiming the coins. The network verifies that the provided key hashes to the stored value, then checks the signature as before.
This one change bought three things. First, shorter outputs: 25 bytes instead of P2PK's 67, because a 20-byte hash replaces a 65-byte key. Second, human-readable addresses: the 20-byte hash, wrapped in Base58Check encoding, produces compact strings like 1BNwxHGaFbeUBitpjy2AsKpJ29Ybxntqvb that can be copied, printed, and shared. Third, a quantum firewall: the public key stays hidden behind a hash until the moment of spending. An attacker who knows only the address cannot derive the public key, much less the private key, without breaking both RIPEMD-160 and SHA-256.
Our specimen for this chapter is the first non-coinbase transaction in Block 100,000—a milestone that the Bitcoin network reached on December 29, 2010, nearly two years after genesis.
Block 100,000 was mined on December 29, 2010 at 11:57 UTC.† By this point, Bitcoin had survived its first major crisis—the value overflow bug of August 2010, which temporarily created 184 billion BTC before being patched within hours—and was beginning to attract interest beyond the cypherpunk community. The exchange rate was approximately $0.30.
Txid (reversed double-SHA-256):†
fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4
Unlike our Block 170 specimen from Part I, where the input spent a P2PK output (providing only a signature in the scriptSig), this transaction both spends a P2PKH output and creates two new P2PKH outputs. It is a pure P2PKH transaction from input to output—the "1-address" paradigm fully realized.
We parse the 259 bytes field by field. The overall structure is identical to what we learned in Chapter 1—version, inputs, outputs, locktime—but now the scripts contain new opcodes.
| Offset | Field | Hex (little-endian) | Value |
|---|---|---|---|
0–3 | Version | 01 00 00 00 | 1 |
4 | Input count | 01 | 1 input |
5–36 | Previous txid | 032e38e9 … 57a187 | big-endian: 87a157f3 … 382e03 |
37–40 | Previous vout | 00 00 00 00 | Output 0 |
41 | ScriptSig length | 8c | 140 bytes |
42–181 | ScriptSig | 49 … d3 | parsed in §5.4 |
182–185 | Sequence | ff ff ff ff | Final (no RBF) |
The previous transaction (87a157f3fd88ac79…) is a coinbase from an earlier block, paying 50 BTC to the P2PKH address 1BNwxHGaFbeUBitpjy2AsKpJ29Ybxntqvb. Our transaction spends that entire 50 BTC UTXO.
| Offset | Field | Hex (little-endian) | Value |
|---|---|---|---|
186 | Output count | 02 | 2 outputs |
| Output 0 | |||
187–194 | Value | 00 e3 23 21 00 00 00 00 | 556,000,000 sats = 5.56 BTC |
195 | SPK length | 19 | 25 bytes |
196–220 | scriptPubKey | 76 a9 14 c3 98 … 32 88 ac | P2PKH to 1JqDybm2… |
| Output 1 | |||
221–228 | Value | 00 0f e2 08 01 00 00 00 | 4,444,000,000 sats = 44.44 BTC |
229 | SPK length | 19 | 25 bytes |
230–254 | scriptPubKey | 76 a9 14 94 … 3d 7c 88 ac | P2PKH to 1EYTGtG4… |
| Trailer | |||
255–258 | Locktime | 00 00 00 00 | 0 (no timelock) |
The fee is \(50.00 - 5.56 - 44.44 = 0\) BTC—zero. In December 2010, this was still common; the network had ample capacity and miners accepted feeless transactions.
Every P2PKH scriptPubKey follows the same 25-byte template:
76 a9 14 <20 bytes> 88 ac
The 76 a9 14 … 88 ac wrapper is a reliable fingerprint. If you see those bytes surrounding a 20-byte payload, you are looking at P2PKH. No other standard script type produces this exact pattern.
Let us decode the 25-byte scriptPubKey of Output 0:
| Hex | Opcode | Effect |
|---|---|---|
76 | OP_DUP | Duplicate top stack item |
a9 | OP_HASH160 | Hash: RIPEMD-160(SHA-256(\(x\))) |
14 | OP_PUSHBYTES_20 | Push next 20 bytes |
c398efa9 c392ba60 13c5e04e e729755e f7f58b32 | pubkey hash | Expected Hash160 |
88 | OP_EQUALVERIFY | Abort if top two \(\neq\) |
ac | OP_CHECKSIG | Verify ECDSA signature |
Compare this with P2PK's scriptPubKey from Chapter 4:
| P2PK | P2PKH | |
|---|---|---|
| Template | <push> <pubkey> OP_CHECKSIG | OP_DUP OP_HASH160 <push> <hash> OP_EQUALVERIFY OP_CHECKSIG |
| Size | 67 bytes (uncompressed) | 25 bytes |
| Key material | Full public key | 20-byte hash |
| Opcodes | 1 | 5 |
The P2PKH scriptPubKey has four additional opcodes but is 42 fewer bytes. The savings come entirely from replacing the 65-byte public key with its 20-byte hash.
Where P2PK's scriptSig contained only a signature, P2PKH's scriptSig must include both the signature and the public key:
| Hex | Element | Size |
|---|---|---|
49 | OP_PUSHBYTES_73 | Push next 73 bytes |
30 46 02 21 00 c3 52 d3 dd 99 3a 98 … af 77 48 | DER-encoded signature | 72 bytes |
01 | SIGHASH_ALL | 1 byte |
41 | OP_PUSHBYTES_65 | Push next 65 bytes |
04 f4 6d b5 e9 d6 1a 9d c2 7b … 12 1d f2 b3 d3 | Uncompressed public key | 65 bytes |
Total: \(1 + 73 + 1 + 65 = 140\) bytes. This is significantly larger than P2PK's scriptSig of \(1 + 73 = 74\) bytes maximum. The extra cost is the public key, which must now travel in the input rather than sitting in the output.
P2PKH does not save total bytes across the transaction lifecycle. It moves them. The scriptPubKey shrinks by 42 bytes, but the scriptSig grows by 66 bytes (the public key plus its push opcode). The net cost of spending a P2PKH output is 24 bytes more than P2PK. The benefits of P2PKH—shorter addresses, quantum resistance before spending, Script-level flexibility—come at the price of larger inputs. We quantify this trade-off precisely in §5.8 P2PKH vs P2PK: The Full Cost.
The 73-byte signature contains the standard DER encoding we parsed in Chapters 1 and 3. This particular signature is notable because both the \(r\) and \(s\) integers require a leading 00 padding byte:
| Field | Hex | Notes |
|---|---|---|
| Sequence marker | 30 | DER SEQUENCE |
| Length | 46 | 70 bytes follow |
| Integer marker | 02 | \(r\) begins |
| \(r\) length | 21 | 33 bytes (padded) |
| \(r\) value | 00 c3 52 d3 dd 99 … 5d ce 82 | Leading 00: high bit of c3 is set |
| Integer marker | 02 | \(s\) begins |
| \(s\) length | 21 | 33 bytes (padded) |
| \(s\) value | 00 84 07 92 bc 1f … af 77 48 | Leading 00: high bit of 84 is set |
| SIGHASH | 01 | SIGHASH_ALL |
The 00 padding is required by the DER standard: without it, the values c3… and 84… would be interpreted as negative integers (their most significant bits are 1). This is the maximum-length DER signature (72 bytes) for secp256k1, producing a 73-byte scriptSig element including the SIGHASH flag.
The 65-byte value starting with 04 is an uncompressed SEC-encoded point on the secp256k1 curve:
| Field | Hex | Size |
|---|---|---|
| Prefix | 04 (uncompressed marker) | 1 byte |
| \(x\)-coordinate | f46db5e9 d61a9dc2 7b8d64ad 23e7383a | 32 bytes |
| \(y\)-coordinate | e825dca6 5046b82c 9331586c 82e0fd1f | 32 bytes |
By late 2010 the Bitcoin software still defaulted to uncompressed keys for most operations. Bitcoin Core would add compressed key support in version 0.6.0 (March 2012). The compressed form—either 02 or 03 followed by just the 32-byte \(x\)-coordinate—saves 32 bytes per input. We will see compressed keys become standard in Chapter 9 (P2WPKH).
One of P2PKH's most visible consequences was the creation of the "Bitcoin address"—a human-readable string that hides the underlying hash. The encoding scheme, called Base58Check, was designed by Satoshi and has three goals:
0, O, I, l)Before encoding an address, we must first transform the public key into a 20-byte hash. This two-stage hash is called Hash160:
The tool above computes every byte. For our specimen's public key (04f46db5e9…1df2b3d3), the two hashing stages produce:
c6efd5e9 c9dac236 5c569d49 2e839967 9cc9eb08 c39f537a b35d4be2 2d87e6f2
71d7dd96 d9edda09 180fe9d5 7a477b5a cc9cad11
These 20 bytes are the pubkey hash that appears inside the scriptPubKey of the previous transaction's output. When the network receives our specimen, it hashes the public key from the scriptSig and checks that the result matches these stored bytes.
Hash160 chains SHA-256 and RIPEMD-160 for defense in depth. SHA-256 was designed by the NSA and standardized by NIST. RIPEMD-160 was designed by European academics (Hans Dobbertin, Antoon Bosselaers, and Bart Preneel at K.U.\ Leuven).† If either algorithm is compromised, the other still provides protection. By chaining hash functions from independent design traditions—American government and European academia—the system avoids a single point of cryptographic failure.
With the 20-byte hash in hand, we build the address in four steps:
00:
00 71d7dd96 d9edda09 180fe9d5 7a477b5a cc9cad11 (21 bytes)
SHA-256d(0071d7dd…9cad11) \(\to\) checksum = 8d b5 e2 0c
00 71d7dd96 d9edda09 180fe9d5 7a477b5a cc9cad11 8db5e20c (25 bytes)
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Each leading 00 byte maps to a leading 1 character.
The result:
1BNwxHGaFbeUBitpjy2AsKpJ29Ybxntqvb
Every P2PKH mainnet address starts with 1. This is not a coincidence—it is a direct consequence of the 00 version byte. When Base58 encounters a leading zero byte, it emits 1 (the first character in the Base58 alphabet). Since all P2PKH addresses have version byte 00, they all begin with 1. Testnet P2PKH uses version byte 6f (111 in decimal), producing addresses starting with m or n.
Satoshi chose Base58 over the more common Base64 because Base64 includes characters that cause problems in practice: + and / break URLs, 0/O and I/l are visually ambiguous in many fonts. By removing these six characters, Base58 sacrifices a small amount of encoding density for significant gains in usability. The 4-byte checksum provides a \(1\) in \(2^{32}\) (\(\approx\) 4.3 billion) chance of an undetected error—virtually zero for random typos.
Now we trace the full execution of our specimen's input validation. As described in Chapter 2, the scriptSig and scriptPubKey are evaluated in sequence: the scriptSig pushes data onto the stack, and the scriptPubKey consumes it.
ScriptSig (from the spending input):
<sig> <pubkey>
ScriptPubKey (from the previous output being spent):
OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG
| Step | Operation | Action | Stack (top \(\to\) right) |
|---|---|---|---|
| 1 | Push <sig> | ScriptSig pushes 73-byte signature | [sig] |
| 2 | Push <pubkey> | ScriptSig pushes 65-byte public key | [sig, pk] |
| 3 | OP_DUP | Duplicate the top item | [sig, pk, pk] |
| 4 | OP_HASH160 | Pop pk; push Hash160(pk) | [sig, pk, h160] |
| 5 | Push <hash> | Push expected 20-byte hash | [sig, pk, h160, hash] |
| 6 | OP_EQUALVERIFY | Pop two; abort if \(\neq\) | [sig, pk] |
| 7 | OP_CHECKSIG | Pop pk and sig; verify ECDSA | [TRUE] |
Let us walk through each step with our actual specimen values.
Steps 1–2: The scriptSig pushes two items. The stack now holds the 73-byte signature (bottom) and the 65-byte public key (top).
Step 3 (OP_DUP): The public key is duplicated. The stack has three items: sig, pk, pk.
Step 4 (OP_HASH160): The top copy of the public key is popped and hashed:
RIPEMD160(SHA256(04f46db5… 2b3d3)) = 71d7dd96 d9edda09 180fe9d5 7a477b5a cc9cad11
The 20-byte result is pushed. Stack: [sig, pk, 71d7dd96… ad11].
Step 5: The 20-byte hash from the scriptPubKey is pushed: 71d7dd96… cc9cad11. The stack now has four items.
Step 6 (OP_EQUALVERIFY): The top two items are compared. Both are 71d7dd96… 9cad11—they match. Both are popped. Stack: [sig, pk].
If they had not matched, execution would abort immediately and the transaction would be invalid. This is the hash verification—the P2PKH "firewall" that proves the spender possesses the correct public key without the scriptPubKey ever having revealed it.
Step 7 (OP_CHECKSIG): The signature and public key are popped. The node computes the sighash (as described in Chapter 3), verifies the ECDSA signature against the public key, and pushes TRUE.
The script succeeds. The 50 BTC is unlocked.
OP_EQUAL pushes TRUE or FALSE onto the stack. OP_EQUALVERIFY is equivalent to OP_EQUAL OP_VERIFY: it checks equality and immediately aborts on failure rather than leaving FALSE on the stack. P2PKH uses OP_EQUALVERIFY because there is no reason to continue execution if the hash check fails—the signature check would be meaningless with the wrong public key.
In Chapter 4 we noted that P2PK outputs expose the public key on the blockchain, making them vulnerable to an adversary who can solve the elliptic curve discrete logarithm problem (ECDLP). P2PKH adds a layer of protection:
If coins are sent to the same P2PKH address twice, the first spend reveals the public key. Any remaining funds at that address—from the second payment—are now protected only by ECDLP, exactly like a P2PK output. This is why the whitepaper advises using a new key pair for every transaction. Despite this, address reuse remained common for years: some exchanges and services used a single deposit address for thousands of customers.
Let us quantify the byte cost of both transaction types across the full UTXO lifecycle. A UTXO is created (in a scriptPubKey) and later consumed (by a scriptSig). We must count both.
| Component | P2PK (uncompressed) | P2PKH (uncompressed) |
|---|---|---|
| scriptPubKey | \(1 + 65 + 1 = 67\) bytes | \(3 + 20 + 2 = 25\) bytes |
| scriptSig (max) | \(1 + 73 = 74\) bytes | \(1 + 73 + 1 + 65 = 140\) bytes |
| Lifecycle total | 141 bytes | 165 bytes |
P2PKH costs 24 extra bytes over its lifetime. But this comparison obscures an important asymmetry: scriptPubKey bytes live in the UTXO set—the database that every full node must hold in memory—while scriptSig bytes are needed only during validation and can then be discarded. From a UTXO-set perspective, P2PKH is dramatically cheaper: 25 bytes vs 67 bytes, a 63% reduction in the most expensive storage on the network.
| Component | P2PK | P2PKH |
|---|---|---|
| scriptPubKey | 67 bytes | 25 bytes |
| scriptSig | 74 bytes | 140 bytes |
| Lifecycle total | 141 bytes | 165 bytes |
| P2PKH costs 24 extra bytes over its lifetime — the price of hiding the pubkey until spend time | ||
With compressed keys (standard from 2012 onward), the comparison shifts:
| Component | P2PK (compressed) | P2PKH (compressed) |
|---|---|---|
| scriptPubKey | \(1 + 33 + 1 = 35\) bytes | \(3 + 20 + 2 = 25\) bytes |
| scriptSig (max) | \(1 + 73 = 74\) bytes | \(1 + 73 + 1 + 33 = 108\) bytes |
| Lifecycle total | 109 bytes | 133 bytes |
Even with compressed keys, P2PKH still costs 24 extra lifecycle bytes. But the UTXO-set savings remain: 25 vs 35 bytes. The fundamental trade-off never changes: P2PKH trades input bloat for output efficiency and the hash-based security model.
P2PKH quickly displaced P2PK as the standard transaction type. The original Bitcoin client switched its default output type from P2PK to P2PKH for non-coinbase transactions early in 2009, and by mid-2010 the vast majority of user-created outputs were P2PKH. Coinbase outputs continued using P2PK until mining pools transitioned in later years.
The first P2PKH output appeared in Block 728, mined on January 16, 2009—thirteen days after genesis. Transaction 6f7cf958…† consolidated two 50-BTC P2PK coinbase outputs into a single 100-BTC P2PKH output at address 12higDjoCCNXSA95xZMWUdPvXNmkAduhWv. This was a transition transaction: P2PK inputs funding a P2PKH output. The old world funding the new.
The "1-address" era lasted from 2009 until SegWit activation in August 2017, when P2SH-wrapped SegWit ("3-addresses") and later native SegWit ("bc1q-addresses") began replacing P2PKH. Even today, P2PKH remains fully valid and understood by all nodes. A significant fraction of Bitcoin's UTXO set still consists of P2PKH outputs, particularly from long-dormant coins.
1, with a 4-byte checksum for error detection.OP_DUP, OP_HASH160, push hash, OP_EQUALVERIFY, OP_CHECKSIG) creates a two-layer verification: first check that the provided key matches the hash, then check the signature.P2PKH solved the address problem and added a hash-based security layer. But it introduced a new limitation: every output can contain only one spending condition—one key, one signature. What if you want to require multiple signatures? What if you want the spending rules to be chosen freely by the recipient—multisig, timelocks, arbitrary conditions—rather than limited to a single key? In Chapter 6, we examine P2SH—Pay to Script Hash—which answers these questions by hashing the entire script rather than just the public key, opening the door to arbitrarily complex spending conditions behind a simple 20-byte hash.
*Exercises
1JqDybm2nWTENrHv\-MyafbSXXtTk5Uv5QAn.00 padding byte?71d7dd96d9edda09\-180fe9d57a477b5acc9cad11).OP_DUP in P2PKH is necessary. What would happen if the script were OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG without it?*Solutions
L1. 0x00.
L2. 25 bytes: 76 a9 14 (3 bytes prefix) + 20-byte hash + 88 ac (2 bytes suffix).
L3. OP_HASH160 (0xa9). Despite its name, this single opcode performs both SHA-256 and RIPEMD-160 in sequence.
L4. \(5,000,000,000 - 556,000,000 - 4,444,000,000 = 0\) satoshis. The fee is zero.
L5. 1. This results from the 0x00 version byte: Base58 maps leading zero bytes to the character 1.
H1. Output 0's scriptPubKey is 76a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac. Stripping the 76 a9 14 … 88 ac template:
c398efa9 c392ba60 13c5e04e e729755e f7f58b32_20-byte pubkey hash
Building the address:
00: 00 c398efa9c392ba6013c5e04ee729755ef7f58b32 (21 bytes).3b e5 31 c3.1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn H2. The DER signature (72 bytes before SIGHASH):
30 46 02 21 00 c3 52 d3 dd 99…5d ce 82 02 21 00 84 07 92 bc 1f… af 77 48
\(r\) length = 33 bytes (0x21). \(s\) length = 33 bytes (0x21). Both require a leading 00 because their first significant byte has the high bit set (c3 = 1100 0011\(_2\) and 84 = 1000 0100\(_2\)). In DER encoding, integers are signed; without the padding, the values would be interpreted as negative.
H3.
04f46db5e9d61a9dc27b…121df2b3d3 (65 bytes).c6efd5e9 c9dac236 5c569d49 2e839967 9cc9eb08 c39f537a b35d4be2 2d87e6f2. RIPEMD-160: 71d7dd96 d9edda09 180fe9d5 7a477b5a cc9cad11.
This matches the prevout scriptPubKey hash 71d7dd96d9edda09180fe9d57a477b5acc9cad11.
H4. With a compressed key (33 bytes instead of 65), the scriptSig would be: \(1 + 73 + 1 + 33 = 108\) bytes instead of 140—a savings of 32 bytes per input, exactly the size of one elliptic curve coordinate.
P1. Without OP_DUP, the script would be:
<sig> <pubkey> | OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG
OP_HASH160 would consume the public key to produce the hash. After OP_EQUALVERIFY succeeds, the stack would contain only [sig]. But OP_CHECKSIG requires two stack items—a signature and a public key. With the public key consumed by the hash operation, OP_CHECKSIG would fail due to insufficient stack items. OP_DUP creates a copy so that one instance is consumed by hashing and the other survives for signature verification.
P2. A Base58Check address encodes 25 raw bytes (21-byte versioned payload + 4-byte checksum). A single-character typo alters the encoded string, which decodes to a different 25-byte sequence. The new sequence will have a valid checksum only if the first 21 decoded bytes, when double-SHA-256-hashed, happen to produce the same first 4 bytes. For a random modification, the probability is \(1/2^{32} \approx 2.33 \times 10^{-10}\), or about 1 in 4.3 billion.
This is far beyond sufficient for accidental errors: a human making a single typo has essentially zero chance of producing a valid address. It is not designed for adversarial forgery—a determined attacker could craft a valid-checksum address by brute force in \(2^{32}\) SHA-256d operations, which is trivial on modern hardware. But the checksum's purpose is error detection, not cryptographic security.
P3. P2PKH's quantum resistance is time-bounded, not absolute. When a P2PKH output is unspent and the address has never been used to send, the public key is unknown—an attacker must break Hash160 to find it. But the moment a spending transaction is broadcast to the mempool, the public key is visible to all nodes. A quantum adversary could:
This attack requires a quantum computer fast enough to break ECDLP within the window between broadcast and confirmation (typically 10–60 minutes). Current estimates suggest this would require millions of logical qubits—far beyond near-term hardware. But P2PKH's protection is not "unbreakable"; it is "unbreakable given the current state of quantum computing." The protection is real today, but its shelf life is finite.
C1.
At Bitcoin's current scale (180 million UTXOs), this matters enormously. If the entire UTXO set were P2PK, the scriptPubKey component alone would require 11.2 GiB. With P2PKH, it is 4.2 GiB—a 7.0 GiB saving, roughly the difference between fitting in RAM on a modest machine and not.
C2. SegWit discounts witness data by a factor of 4 in the weight calculation. For P2WPKH (the SegWit equivalent of P2PKH), the signature and public key move to the witness:
This means the "input bloat" of P2PKH—the extra bytes of public key in the scriptSig—is no longer penalized at full rate. SegWit effectively eliminates the size trade-off that P2PKH introduced, giving the benefits of hash-based addresses (compact outputs, quantum firewall) without the fee penalty of carrying the public key in the expensive part of the transaction.
B1. A bare 2-of-3 multisig scriptPubKey with uncompressed keys:
OP_2 <65B key1> <65B key2> <65B key3> OP_3 OP_CHECKMULTISIG
Size: \(1 + (1+65) \times 3 + 1 + 1 = 201\) bytes.
The equivalent P2SH scriptPubKey:
OP_HASH160 OP_PUSHBYTES_20 <20-byte script hash> OP_EQUAL
Size: \(1 + 1 + 20 + 1 = 23\) bytes. The full 201-byte redeem script moves to the scriptSig, provided only when spending. The output shrinks from 201 to 23 bytes—an 88.6% reduction.
B2. Three problems with Base58Check that Bech32 solves: