Part II · The Classic Era Chapter 6

Pay to Script Hash (P2SH)

"All problems in computer science can be solved by another level of indirection."—David Wheeler

By early 2012, Bitcoin had a problem. P2PKH gave every user an address—a compact, checksummed representation of their public key hash—but what if the spending conditions were more complex than a single signature? A company that required two-of-three board approval for expenditures could construct a multisig script, but the sender would need to embed the full script—three public keys and all the associated opcodes—into the output's scriptPubKey. For a 2-of-3 multisig with compressed keys, this meant 105 bytes in the scriptPubKey, compared to P2PKH's tidy 25. The sender had to know the recipient's full script, not just an address. There were no "multisig addresses."

P2SH—Pay to Script Hash—solved this with exactly the level of indirection that David Wheeler prescribed. Instead of embedding the full spending script in the output, hash it. The scriptPubKey stores only the 20-byte hash of the script. When the recipient spends the coins, they provide the full script (called the redeem script) in the scriptSig, along with whatever data the redeem script requires. The network verifies that the provided script hashes to the stored value, then executes it.

The result: every P2SH output is exactly 23 bytes, regardless of the complexity of the underlying script. A simple single-signature and a 15-of-15 multisig look identical on-chain until they are spent. And P2SH addresses—beginning with 3—gave users a standard format for receiving funds into any script.

BIP 16: The First Contentious Upgrade

P2SH was proposed as BIP 16 by Gavin Andresen in January 2012. An earlier proposal, OP_EVAL (BIP 12, also by Andresen), would have added a general-purpose script evaluation opcode, but was withdrawn due to concerns about Turing-completeness and denial-of-service vectors. A competing alternative, BIP 17 by Luke Dashjr, proposed a new opcode (OP_CHECKHASHVERIFY) but was also withdrawn. BIP 16 took the narrowest approach: a special-case rule that applies only to scripts matching the exact pattern OP_HASH160 <20 bytes> OP_EQUAL. The activation was contentious—some miners signaled opposition—but P2SH ultimately activated on April 1, 2012 at block height 173,805.

6.1The Specimen

Our specimen is a 2-of-3 multisig P2SH transaction from Block 450,000, mined on January 25, 2017.

Txid:

521f7c6781ced91da6cc8eb4c64b283d2e99f98627daf8a3a0c60432d8e8f601

This is a single-input, two-output transaction. The input spends a P2SH 2-of-3 multisig output, providing two of three required signatures plus the full redeem script. Both outputs pay to new P2SH addresses (the "3-address" format).

6.2The P2SH ScriptPubKey

Every P2SH scriptPubKey is exactly 23 bytes:

P2SH ScriptPubKey Template
HexOpcodeEffect
a9OP_HASH160Hash top stack item
14OP_PUSHBYTES_20Push next 20 bytes
<20 bytes>script hashExpected Hash160 of redeem script
87OP_EQUALPush TRUE if equal

Our specimen's prevout scriptPubKey is: a9 14 d0982dd3 91d674f1 01898e85 00586019 e01d9aa7 87

23 Bytes for Any Complexity

Compare the P2SH scriptPubKey (23 bytes) with the bare 2-of-3 multisig it replaces (105 bytes in the scriptPubKey alone). Regardless of whether the redeem script contains a simple single-key check or a complex 15-of-15 multisig, the on-chain output is always 23 bytes. The complexity is hidden until spending time—and the cost of revealing it is borne by the spender, not the sender.

6.3The P2SH ScriptSig

The P2SH scriptSig must contain everything needed to satisfy the redeem script, followed by the redeem script itself:

P2SH ScriptSig — Input 0 (253 bytes)
HexElementSize
00OP_0 (multisig dummy)1 byte
47OP_PUSHBYTES_71Push 71 bytes
3044… f3201DER signature 1 + SIGHASH71 bytes
48OP_PUSHBYTES_72Push 72 bytes
3045… da4f01DER signature 2 + SIGHASH72 bytes
4cOP_PUSHDATA1Next byte is length
69Length = 105105-byte redeem script follows
5221…53aeRedeem script105 bytes

Total: \(1 + 1 + 71 + 1 + 72 + 2 + 105 = 253\) bytes. The scriptSig is structured in two layers: first the data that satisfies the redeem script (the dummy byte and two signatures), then the redeem script itself as the final push.

The Dummy Byte

The 00 at the start of the scriptSig is a consequence of the OP_CHECKMULTISIG off-by-one bug described in Chapter 2. This opcode pops one more item from the stack than it should, so an extra dummy value must be provided. BIP 147 (enforced since SegWit activation) requires this dummy to be exactly OP_0; any other value causes the transaction to be rejected.

6.4The Redeem Script

The 105-byte redeem script at the end of the scriptSig encodes a 2-of-3 multisig:

Redeem Script (105 bytes)
HexOpcodeMeaning
52OP_2\(m = 2\) signatures required
21OP_PUSHBYTES_33Push 33-byte compressed key
02ca355b…0de7Public key 133 bytes
21OP_PUSHBYTES_33Push 33-byte compressed key
03e5fa93…495fPublic key 233 bytes
21OP_PUSHBYTES_33Push 33-byte compressed key
03ee6664… ec21Public key 333 bytes
53OP_3\(n = 3\) keys total
aeOP_CHECKMULTISIGVerify \(m\)-of-\(n\)

The redeem script is a self-contained Bitcoin Script. It says: "of these three public keys, at least two must provide valid signatures." The Hash160 of this 105-byte script is:

d0982dd3 91d674f1 01898e85 00586019 e01d9aa7

Sender vs Receiver Responsibility

In P2SH, the receiver constructs the redeem script and computes its hash. They give the sender only the 20-byte hash (as a "3-address"). The sender creates an output locked to that hash without ever seeing the redeem script. When the receiver later spends the output, they reveal the redeem script—and only then does the network learn the actual spending conditions.

🔧 Interactive: Redeem Script Anatomy

6.5Two-Phase Evaluation

P2SH validation happens in two distinct phases. This is the key innovation—and the source of its controversy.

🔧 Interactive: P2SH Two-Phase Evaluator

6.5.1Phase 1: Hash Check

First, the node evaluates the scriptSig against the scriptPubKey as usual. The scriptPubKey is OP_HASH160 <hash> OP_EQUAL. The last item pushed by the scriptSig—the serialized redeem script—lands on top of the stack. OP_HASH160 hashes it, and OP_EQUAL compares the result to the stored hash.

Step | Operation | Action | Stack

1–4 | ScriptSig pushes | OP_0, sig1, sig2, redeem | [0, s1, s2, rs]

5 | OP_HASH160 | Hash the redeem script | [0, s1, s2, h]

6 | Push <hash> | Push expected hash | [0, s1, s2, h, h']

7 | OP_EQUAL | Compare hashes | [0, s1, s2, TRUE]

If the hashes do not match, validation fails immediately—the redeem script is a forgery.

6.5.2Phase 2: Script Execution

Here is where P2SH departs from normal Script evaluation. After Phase 1 succeeds, the node recognizes this as a P2SH transaction (because the scriptPubKey matched the exact a9 14 … 87 pattern). It then deserializes the redeem script and executes it as a new script, using the remaining items on the stack (everything below the redeem script) as its input.

Step | Operation | Action | Stack

| Start Phase 2 | Stack from Phase 1 (minus hash result) | [0, s1, s2]

8 | OP_2 | Push \(m = 2\) | [0, s1, s2, 2]

9–11 | Push keys | Push three 33-byte pubkeys | [0, s1, s2, 2, pk1, pk2, pk3]

12 | OP_3 | Push \(n = 3\) | […, 3]

13 | OP_CHECKMULTISIG | Verify 2-of-3 | [TRUE]

OP_CHECKMULTISIG pops \(n + m + 3\) items from the stack: the dummy OP_0, the two signatures, the number 2, the three public keys, and the number 3. It verifies that at least 2 of the 3 keys have valid corresponding signatures. If so, it pushes TRUE.

P2SH Is a Special Rule, Not a Script Feature

P2SH is not implemented as a Script opcode. It is a consensus rule that triggers when the scriptPubKey matches a specific pattern. This means P2SH cannot be nested—you cannot create a P2SH output whose redeem script is itself a P2SH script. This was a deliberate design choice to keep validation simple and predictable.

6.6P2SH Addresses

P2SH uses the same Base58Check encoding as P2PKH, but with version byte 05 instead of 00:

  1. Hash160 the redeem script: d0982dd3 91d674f1 01898e85 00586019 e01d9aa7
  2. Prepend version byte 05: 05 d0982dd3… e01d9aa7 (21 bytes)
  3. Compute 4-byte SHA-256d checksum and append
  4. Base58-encode the 25-byte result

Result: 3Lhxn2YXvoQzM2CvbVxQgrvYAYaswb9jK1

The version byte 05 produces addresses beginning with 3 (on mainnet), distinguishing them from P2PKH's 1-prefix addresses. This lets wallets and users identify at a glance whether they are sending to a simple key hash or a script hash.

BIP 13: The "3-Address" Standard

BIP 13, also by Gavin Andresen, defined the address format for P2SH. By assigning version byte 05, all P2SH addresses start with 3. This was a deliberate visual signal: a "3-address" tells the sender that the recipient uses a more complex spending condition (multisig, timelock, or other script), but the sender does not need to know or care what it is.

🔧 Interactive: P2SH Address Derivation

6.7P2SH Size Analysis

P2SH shifts the cost of complex scripts from output creation to spending:

Component | Bare 2-of-3 | P2SH 2-of-3

scriptPubKey | 105 bytes | 23 bytes

scriptSig | \(1 + 72 + 73 = 146\) bytes | \(1 + 72 + 73 + 107 = 253\) bytes

Lifecycle total | 251 bytes | 276 bytes

Like P2PKH, P2SH costs more total bytes. The scriptPubKey shrinks by 82 bytes, but the scriptSig grows by 107 bytes (the redeem script and its push opcode). But the UTXO-set savings are dramatic: 23 bytes vs 105 bytes, a 78% reduction in the most expensive storage.

6.8What We Learned

6.8.1Looking Ahead

P2SH gave Bitcoin arbitrarily complex spending conditions behind a uniform 23-byte output. But it also introduced a new cost: the full redeem script must be revealed on-chain when spending, adding significant weight to transactions. In Chapter 7, we examine multisig in detail—both bare and P2SH-wrapped—exploring the OP_CHECKMULTISIG opcode, its famous off-by-one bug, and the \(m\)-of-\(n\) combinations that made P2SH indispensable.

*Exercises

Litmus (L)

  1. What is the version byte for a mainnet P2SH address?
  2. How many bytes is a P2SH scriptPubKey?
  3. What three opcodes appear in every P2SH scriptPubKey?
  4. Why does the scriptSig begin with OP_0?
  5. What is the fee in our specimen, in satoshis?

Hands-On (H)

  1. Compute the Hash160 of the redeem script from our specimen. Verify it matches the prevout's script hash (d0982dd391d674f1\-01898e8500586019e01d9aa7).
  2. Extract the three public keys from the redeem script. How can you tell they are compressed?
  3. Compute the P2SH address for Output 0's script hash:
  4. 3aa40fcb5b0f6b41c7eb67f8c2fc627da9d49b44.

  5. What would the scriptSig size be for a 3-of-5 P2SH multisig with compressed keys?

Proofs and Reasoning (P)

  1. Explain why P2SH cannot be nested (a P2SH redeem script cannot itself be P2SH). What would go wrong if it could?
  2. Why does P2SH use OP_EQUAL instead of OP_EQUALVERIFY in the scriptPubKey?
  3. Prove that a P2SH output reveals nothing about the spending conditions until the output is spent.

Connections (C)

  1. P2SH-P2WPKH (Chapter 11) wraps a SegWit script inside a P2SH redeem script for backward compatibility. Write out the full scriptSig for such a transaction.
  2. Compare the UTXO-set cost of 1 million bare 2-of-3 multisig outputs vs 1 million P2SH 2-of-3 outputs.

Bridge (B)

  1. How does P2WSH (Chapter 10) differ from P2SH? What hash function does it use, and why is the hash 32 bytes instead of 20?
  2. Taproot (Chapter 12) eliminates the need for P2SH in many cases. Explain how a 2-of-3 multisig could be represented as a Taproot output without revealing the multisig structure.

*Solutions

L1. 0x05.

L2. 23 bytes: a9 14 (2 bytes) + 20-byte script hash + 87 (1 byte).

L3. OP_HASH160 (0xa9), OP_PUSHBYTES_20 (0x14), and OP_EQUAL (0x87).

L4. The OP_CHECKMULTISIG off-by-one bug causes it to pop one extra item from the stack. The dummy OP_0 is consumed by this bug. BIP 147 requires it to be exactly OP_0 (not any other value) as a standardness and consensus rule.

L5. \(25,605,948 - 24,500,000 - 1,043,948 = 62,000\) satoshis.

H1. The redeem script (105 bytes) starts with 52 21 02ca… and ends with … 53 ae.

  1. SHA-256(105-byte redeem script) \(\to\) 32-byte intermediate hash.
  2. RIPEMD-160(32-byte hash) \(\to\) d0982dd3 91d674f1 01898e85 00586019 e01d9aa7.

This matches the prevout script hash.

H2. The three public keys are:

  1. 02ca355b567bff51c9b4a1c1590e25f685f8d12273efb7f7685a50e546786d0de7
  2. 03e5fa93cffa7533c6b68906c4a9b8665f5167f3ed95b830328835ca4d39b6495f
  3. 03ee6664f625e0a44fad0ad53ae1ecdc7c7239346b81514e8f87cfd2be4f8fec21

They are compressed because each is 33 bytes and begins with 02 or 03 (the parity prefix for the \(y\)-coordinate). An uncompressed key would be 65 bytes starting with 04.

H3. Script hash 3aa40fcb5b0f6b41c7eb67f8c2fc627da9d49b44:

  1. Prepend version 05: 05 3aa40fcb… d49b44 (21 bytes).
  2. SHA-256d checksum (first 4 bytes): compute and append.
  3. Base58-encode: 3735esnd2JiPEfZzanKeZf7gAH42kMGGir

H4. A 3-of-5 P2SH multisig scriptSig:

Total: \(1 + 219 + 2 + 173 = 395\) bytes (max).

P1. P2SH is a consensus rule that fires when the scriptPubKey matches OP_HASH160 <20> OP_EQUAL. If the redeem script itself were P2SH (another a9 14 … 87 pattern), Phase 2 would need to trigger again on the inner script—requiring recursive evaluation. This was deliberately forbidden because: (a) recursion could enable unbounded computation depth, creating denial-of-service vectors; (b) it complicates validation logic for all nodes; (c) there is no practical use case that requires nesting, since a single P2SH layer can wrap arbitrarily complex scripts.

P2. P2SH uses OP_EQUAL rather than OP_EQUALVERIFY because the P2SH consensus rule needs to examine the result of the comparison. After Phase 1, the node checks whether the top stack item is TRUE to decide if Phase 2 should proceed. If OP_EQUALVERIFY were used, the result would be consumed (VERIFY pops TRUE on success)—leaving nothing for the P2SH rule to inspect. The two-phase model requires the hash-check result to remain on the stack.

P3. A P2SH scriptPubKey contains only OP_HASH160 OP_PUSHBYTES_20 <20-byte hash> OP_EQUAL (23 bytes). The 20-byte hash is the Hash160 of the redeem script, which is a preimage-resistant one-way function. Given only the hash, an observer cannot determine: (a) how many keys are involved, (b) what the threshold is (\(m\)-of-\(n\)), (c) whether timelocks or other conditions exist, or (d) the total size of the script. All P2SH outputs look identical: 23 bytes in the same format. Only when the output is spent does the scriptSig reveal the redeem script.

C1. A P2SH-P2WPKH scriptSig contains only the redeem script (no signatures—those move to the witness):

00 14 <20-byte witness program>

The redeem script is 00 14 <20-byte key hash> (22 bytes), which is the P2WPKH witness program. The scriptSig pushes this 22-byte script. Total scriptSig: \(1 + 22 = 23\) bytes. The actual signature and public key appear in the segregated witness field.

C2.

B1. P2WSH uses SHA-256 (not Hash160) to hash the witness script, producing a 32-byte hash instead of 20. The longer hash provides \(2^{128}\) collision resistance (vs \(2^{80}\) for Hash160's 20-byte output), which matters because P2SH's 20-byte hash is vulnerable to birthday attacks—a 2-of-2 multisig counterparty could theoretically find a colliding script with \(2^{80}\) work. The P2WSH scriptPubKey is OP_0 <32-byte SHA-256 hash> (34 bytes).

B2. In Taproot, a 2-of-3 multisig can be split into three 2-of-2 key combinations (\(32 = 3\) pairs). Each pair is aggregated into a single Schnorr public key using MuSig2. The three aggregated keys form three script leaves in a Taproot Merkle tree. The output looks like a standard P2TR key-path output (34 bytes)—indistinguishable from a single-signature spend. If two of three participants cooperate, they can spend via the corresponding script leaf, revealing only that leaf (not the others). In the best case (key-path spend via a designated quorum), the multisig is completely invisible on-chain.

← Ch. 5 Ch. 7 →