Blockchain/Level IV · Protocol depth/4.1 Script/Lesson 2
Standard scripts: P2PKH and P2SH
Locking coins to a key, then to the hash of any script
MaterialsA block explorer interface (e.g., Blockstream.info or mempool.space)A SHA-256 and RIPEMD-160 hashing toolHexadecimal reference chartA block explorer capable of viewing raw transaction hex
Wonder
- Why does Bitcoin lock coins to a hash rather than the key itself?
- How does a four-line script verify both ownership and authorization in one execution?
- What made P2PKH the default address format for over eight years of the network’s history?
Explore
- The genesis block contained only Pay-to-Public-Key (P2PK) outputs. These scripts placed the full public key (in 2009, a 65-byte uncompressed key) directly in the output, visible before any spend, and made outputs large. P2PKH, also present in the original 2009 software and used for ordinary address payments, stores a 20-byte hash instead, hiding the key until the coins are spent.
- The locking script is `OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG`. Execution begins with the spender’s data on the stack: the signature, then the public key on top. The engine duplicates the key, hashes it using RIPEMD-160(SHA256(key)), and compares the result to the stored hash. If they match, `OP_EQUALVERIFY` passes; otherwise, execution halts immediately.
- Once the hash check succeeds, `OP_CHECKSIG` verifies the ECDSA signature against the revealed public key and the transaction data. This dual mechanism ensures only the holder of the corresponding private key can unlock the funds. The output script totals 25 bytes, a compact structure that became the basis for legacy addresses starting with ‘1’.
- P2PKH was the most common output type for ordinary payments for most of bitcoin’s history, and remained so for years after SegWit activated in August 2017 at block 481,824, because adoption of native SegWit was gradual. Its success lay in simplicity and compatibility; it required no consensus upgrades beyond the original protocol rules. Every node could validate these scripts independently without complex state tracking, making it the most robust output type for general-purpose transfers during Bitcoin’s early growth.
- The address format uses Base58Check encoding, which includes a four-byte checksum to detect typos. A single mistyped character will almost certainly fail the checksum, so the wallet refuses the address. This redundancy made P2PKH user-friendly despite its raw technical complexity, bridging the gap between cryptographic security and human usability.
- Open a block explorer and locate any transaction with an input referencing a ‘1’ address. Examine the `scriptSig` field: it contains the signature followed by the public key hex string. Compare this public key against the 20-byte hash in the referenced output’s `scriptPubKey`. Running SHA-256 then RIPEMD-160 on that key will reproduce the stored hash, confirming the link.
- Before 2012, using a complex script like a five-of-five multisignature required placing the entire locking code directly into the output. This made the output large, and the sender paid the fee for it. It also exposed every participant’s public keys and the specific signing requirements to anyone watching the chain. The sender had to know the exact structure of the destination before sending, creating friction for corporate treasuries or exchanges that needed flexible security configurations.
- Gavin Andresen proposed BIP16 at the start of 2012 to solve this. It allowed an output to contain only the HASH160 digest of a script rather than the script itself. The output script shrank to 23 bytes, slightly smaller than P2PKH’s 25. The sender no longer needed to know the spending conditions; they simply paid to a hash. The complexity was shifted entirely to the person spending the coins.
- The activation of BIP16 in April 2012 was contentious. Luke Dashjr proposed an alternative, BIP17, which used a different opcode and encoding scheme. The debate over which proposal to adopt heated up significantly within the developer community. BIP16 was activated in April 2012 after miners signaled support, and became the standard way to wrap complex scripts.
- Spending a pay-to-script-hash output is a two-stage process. First, the spender pushes their full redeem script onto the stack. The node checks if the HASH160 of that script matches the hash in the output. If it does not match, execution fails immediately. If it matches, the node then executes the revealed redeem script with the remaining data on the stack to verify the actual spending conditions.
- The design has a sharp edge: nobody can check the redeem script before payment, because only its hash is on-chain. If the receiver’s software built a faulty script, or the script is lost, coins paid to that address can be unspendable forever.
- When SegWit activated in August 2017, P2SH served as a compatibility bridge. Users could wrap new witness scripts inside a P2SH envelope, creating ‘nested’ addresses that still began with ‘3’. Old wallets that could not handle the newer bech32 addresses could still send to SegWit users, while the SegWit-aware recipients got the fee discount when spending. Today, while native SegWit is preferred for efficiency, P2SH remains a vital mechanism for complex contracts and legacy compatibility.
Part IPay-to-public-key-hash (P2PKH)
Part IIPay-to-script-hash (P2SH)
Key facts
- P2PKH outputs store a 20-byte HASH160 of the public key rather than the full key.
- The locking script `OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG` is exactly 25 bytes long.
- Spending requires revealing both a valid ECDSA signature and the public key matching the stored hash.
- Legacy P2PKH addresses begin with ‘1’ and use Base58Check encoding with a checksum.
- P2PKH was the dominant output type for ordinary payments for years, before and after SegWit.
- Execution fails immediately if `OP_EQUALVERIFY` detects a mismatch between the hashed key and stored hash.
- BIP16 was proposed by Gavin Andresen and activated in April 2012.
- A P2SH output script holds only the HASH160 of a redeem script and is 23 bytes long.
- Luke Dashjr’s BIP17 competed with BIP16 during the heated debate of January to March 2012.
- Redeem scripts are limited to 520 bytes by consensus, the maximum size of a single pushed element.
- P2SH addresses use Base58Check encoding and always begin with the digit ‘3’.
- Nested SegWit (usually P2SH-P2WPKH) let old wallets pay SegWit users after 2017.
Exercise nine, six, three, one
9CollectIdentify 9 real-world transaction inputs on the Bitcoin blockchain that spend from P2PKH addresses. Record their block height, the public key revealed in the scriptSig, and the corresponding hash in the output.
6ClusterGroup the 9 into 6 by era: 2009-2011, 2012-2013, 2014-2015, 2016-2017, 2018-2021, 2022 onward. Note compressed versus uncompressed keys.
3DistillReduce these groups to 3 distinct reasons why P2PKH remained dominant despite the availability of more efficient output types after 2017.
1CrystallizeWrite one sentence explaining how `OP_EQUALVERIFY` transforms a public key into a binding commitment before signature verification occurs.
Fact check
Dates, figures and claims checked against the published sources listed below.
- A. M. Antonopoulos & D. A. Harding, Mastering Bitcoin, 3rd ed. (2023), ch. 7
- Bitcoin Developer Guide, 'Transactions' documentation (bitcoin.org)
- Satoshi Nakamoto, original Bitcoin client source code (2009-2010 commits)
- Gavin Andresen, BIP16: Pay to Script Hash (2012)
- Luke Dashjr, BIP17: OP_CHECKHASHVERIFY (CHV) (2012)
- Bitcoin Developer Guide: Transactions and Scripts