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.
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.
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).
Every P2SH scriptPubKey is exactly 23 bytes:
| Hex | Opcode | Effect |
|---|---|---|
a9 | OP_HASH160 | Hash top stack item |
14 | OP_PUSHBYTES_20 | Push next 20 bytes |
<20 bytes> | script hash | Expected Hash160 of redeem script |
87 | OP_EQUAL | Push TRUE if equal |
Our specimen's prevout scriptPubKey is: a9 14 d0982dd3 91d674f1 01898e85 00586019 e01d9aa7 87
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.
The P2SH scriptSig must contain everything needed to satisfy the redeem script, followed by the redeem script itself:
| Hex | Element | Size |
|---|---|---|
00 | OP_0 (multisig dummy) | 1 byte |
47 | OP_PUSHBYTES_71 | Push 71 bytes |
3044… f3201 | DER signature 1 + SIGHASH | 71 bytes |
48 | OP_PUSHBYTES_72 | Push 72 bytes |
3045… da4f01 | DER signature 2 + SIGHASH | 72 bytes |
4c | OP_PUSHDATA1 | Next byte is length |
69 | Length = 105 | 105-byte redeem script follows |
5221…53ae | Redeem script | 105 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 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.
The 105-byte redeem script at the end of the scriptSig encodes a 2-of-3 multisig:
| Hex | Opcode | Meaning |
|---|---|---|
52 | OP_2 | \(m = 2\) signatures required |
21 | OP_PUSHBYTES_33 | Push 33-byte compressed key |
02ca355b…0de7 | Public key 1 | 33 bytes |
21 | OP_PUSHBYTES_33 | Push 33-byte compressed key |
03e5fa93…495f | Public key 2 | 33 bytes |
21 | OP_PUSHBYTES_33 | Push 33-byte compressed key |
03ee6664… ec21 | Public key 3 | 33 bytes |
53 | OP_3 | \(n = 3\) keys total |
ae | OP_CHECKMULTISIG | Verify \(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
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.
P2SH validation happens in two distinct phases. This is the key innovation—and the source of its controversy.
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.
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 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.
P2SH uses the same Base58Check encoding as P2PKH, but with version byte 05 instead of 00:
d0982dd3 91d674f1 01898e85 00586019 e01d9aa705: 05 d0982dd3… e01d9aa7 (21 bytes)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†, 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.
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.
3 (version byte 05) and are always 23 bytes in the scriptPubKey.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
OP_0?d0982dd391d674f1\-01898e8500586019e01d9aa7).3aa40fcb5b0f6b41c7eb67f8c2fc627da9d49b44.
OP_EQUAL instead of OP_EQUALVERIFY in the scriptPubKey?*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.
d0982dd3 91d674f1 01898e85 00586019 e01d9aa7.This matches the prevout script hash.
H2. The three public keys are:
02ca355b567bff51c9b4a1c1590e25f685f8d12273efb7f7685a50e546786d0de703e5fa93cffa7533c6b68906c4a9b8665f5167f3ed95b830328835ca4d39b6495f03ee6664f625e0a44fad0ad53ae1ecdc7c7239346b81514e8f87cfd2be4f8fec21They 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:
05: 05 3aa40fcb… d49b44 (21 bytes).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):
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.