Chapter 9 showed how P2WPKH moves a single signature and public key into the witness. But Bitcoin's power lies in scripts—arbitrary spending conditions beyond a single key. Multisig, timelocks, hash-locks, and complex smart contracts all require more than one public key and more than one opcode.
Pay to Witness Script Hash (P2WSH) is SegWit's answer to P2SH. It commits to an arbitrary script—the witnessScript—via a 32-byte SHA-256 hash embedded in the scriptPubKey. When the output is spent, the entire witnessScript is revealed in the witness along with the data needed to satisfy it. Like P2WPKH, the scriptSig is empty, the witness data is discounted at 1 WU per byte, and the txid is immune to third-party malleability.
Our specimen comes from block 700,000—mined on September 11, 2021. It is a 2-of-3 multisig P2WSH transaction: one input spending from a P2WSH output, two outputs (one P2SH, one P2WSH change). At 380 bytes and 758 WU, it performs the same 2-of-3 multisig operation as our P2SH specimen from Chapter 6 (370 bytes, 1,480 WU)—but at half the fee.
Txid:
ed25927576988e38e4cc8e4b19d1272c480f113fb605271b190df05aa983714e†
The most striking feature: the scriptSig is empty (0x00), just like P2WPKH. All the spending data—the dummy byte, two signatures, and the entire 105-byte witnessScript—lives in the witness.
P2WSH is the SegWit replacement for P2SH (Chapter 6), but with several important improvements:
| Property | P2SH (Ch. 6) | P2WSH |
|---|---|---|
| Script hash | HASH160 (20 bytes) | SHA-256 (32 bytes) |
| Hash in scriptPubKey | Yes (23 bytes) | Yes (34 bytes) |
| ScriptSig | Sigs + redeem script | Empty (0 bytes) |
| Script location | scriptSig | Witness |
| Weight per script byte | 4 WU | 1 WU |
| Script size limit | 520 bytes | 10,000 bytes |
| Signature digest | Legacy | BIP 143 |
| Address format | 3… (Base58Check) | bc1q… (bech32) |
A P2WSH scriptPubKey is 34 bytes:
| Hex | Opcode | Meaning |
|---|---|---|
00 | OP_0 | Witness version 0 |
20 | OP_PUSHBYTES_32 | Push next 32 bytes |
701a… c58d | (data) | SHA-256 of the witnessScript |
The critical difference from P2SH: the hash is SHA-256 (32 bytes), not HASH160 (20 bytes). BIP 141 uses the witness program length to distinguish the two version-0 types: 20 bytes means P2WPKH, 32 bytes means P2WSH.
P2SH uses HASH160 (RIPEMD-160 of SHA-256), which provides only 80 bits of collision resistance. For a single public key (P2WPKH), collision resistance matters less—the attacker would need to find a different public key with the same hash, which requires a preimage attack (\(2^{160}\) work). But for scripts with multiple spending paths, an attacker who controls one path could craft a collision: a different script with the same hash that redirects funds. SHA-256's 128 bits of collision resistance makes this computationally infeasible.
Our specimen's witness contains four items:
| Hex | Element | Details |
|---|---|---|
04 | Item count | 4 items |
00 | Item 0 (dummy) | Empty (CHECKMULTISIG bug) |
47 | Item 1 length | 71 bytes |
3044…2b01 | DER sig 1 + SIGHASH_ALL | \(r\): 32 B, \(s\): 32 B |
47 | Item 2 length | 71 bytes |
3044…5501 | DER sig 2 + SIGHASH_ALL | \(r\): 32 B, \(s\): 32 B |
69 | Item 3 length | 105 bytes |
5221…53ae | WitnessScript | 2-of-3 (OP_2 [3 keys] OP_3 OP_CMS) |
Total witness: \(1 + 1 + 1 + 71 + 1 + 71 + 1 + 105 = 252\) bytes.
The witnessScript is the last item on the witness stack. The node pops it off, computes its SHA-256 hash, and verifies it matches the 32-byte witness program in the scriptPubKey. Then the remaining witness items (dummy, sig 1, sig 2) are used as input to execute the witnessScript:
SHA-256(5221…53ae) = 701a8d40… ff8c58d
P2WSH validation proceeds in three steps:
OP_0 <32 bytes> in the scriptPubKey, identifies it as a version-0 witness program with a 32-byte program, and invokes P2WSH rules.For our 2-of-3 multisig specimen, the execution proceeds exactly as in Chapter 7:
The off-by-one bug (Chapter 7) applies identically—OP_CHECKMULTISIG pops one extra item (the dummy OP_0), which BIP 147 requires to be empty.
| Component | Value |
|---|---|
| Total size | 380 bytes |
| Marker + flag | 2 bytes |
| Witness data | 252 bytes |
| Stripped size | \(380 - 2 - 252 = 126\) bytes |
| Weight | \(126 \times 3 + 380 = 378 + 380 = 758\) WU |
| Virtual size | \(\lceil 758/4 \rceil = 190\) vbytes |
| Fee | 50,000 sats |
| Fee rate | \(50{,}000 \div 190 \approx 263\) sat/vbyte |
Both our Ch. 6 specimen (P2SH) and this specimen (P2WSH) perform 2-of-3 multisig. The comparison is dramatic:
| Metric | P2SH (Ch. 6) | P2WSH | Savings |
|---|---|---|---|
| Total size | 370 bytes | 380 bytes | \(-10\) (larger!) |
| ScriptSig | 253 bytes | 0 bytes | \(-253\) |
| Witness | 0 bytes | 252 bytes | \(+252\) |
| Weight | 1,480 WU | 758 WU | \(-\)722 (49%) |
| Virtual size | 370 vbytes | 190 vbytes | \(-\)180 (49%) |
P2WSH is actually 10 bytes larger in raw size than P2SH (the 34-byte P2WSH scriptPubKey is 11 bytes larger than P2SH's 23 bytes). But it is nearly 50% cheaper in fees because the 252 bytes of signatures and script data cost only 1 WU each instead of 4.
For P2WPKH (Chapter 9), the fee savings were 38%. For P2WSH multisig, the savings are 49%. The more data that moves to the witness, the greater the discount. A 2-of-3 multisig has 252 bytes of witness data versus P2WPKH's 107—more than twice as much data benefiting from the 4:1 discount.
P2SH imposes a 520-byte limit on the redeem script (the maximum data push in Bitcoin Script). This limits P2SH multisig to 15-of-15 (Chapter 7).
P2WSH raises this limit to 10,000 bytes for the witnessScript. The witnessScript is delivered in the witness, not as a data push in Script, so the 520-byte push limit does not apply. This enables:
While the witnessScript itself can be up to 10,000 bytes, each individual witness stack item (signature, public key, or other data) is still limited to 520 bytes. The witnessScript gets its own limit because it is handled specially by the validation logic, not pushed onto the stack as a single data element.
OP_0 <32>, 34 bytes).5221…53ae and confirm it matches the witness program 701a… c58d.3NL8…) and one to P2WSH (bc1q…). Why might a wallet produce mixed output types?L1. 34 bytes: OP_0 (1) + OP_PUSHBYTES_32 (1) + SHA-256 hash (32). P2SH is 23 bytes (OP_HASH160 <20> OP_EQUAL). P2WPKH is 22 bytes (OP_0 <20>). P2WSH is the largest because it uses a 32-byte hash for stronger collision resistance.
L2. By the witness program length. A 20-byte program is P2WPKH; a 32-byte program is P2WSH. Any other length for version 0 causes the script to fail.
L3. SHA-256 (32 bytes), providing 128 bits of collision resistance. HASH160 provides only 80 bits of collision resistance, which is insufficient for scripts with multiple spending paths where an attacker might craft a collision.
L4. The empty dummy item (0x00) is consumed by OP_CHECKMULTISIG's off-by-one bug—it pops \(n + m + 3\) items instead of \(n + m + 2\). BIP 147 (NULLDUMMY) requires this extra item to be empty.
L5. 10,000 bytes. This is much larger than P2SH's 520-byte limit and enables complex multi-path scripts.
H1. From the 380-byte hex:
H2. The witnessScript is:
5221 0375e0…976b7c 2103a1b2…96feff 2103c96d… f9f880 53ae
SHA-256 of these 105 bytes yields:
701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d
This matches the 32-byte witness program in the scriptPubKey 0020701a… c58d.
H3. The witnessScript decodes as:
52 = OP_2 (\(m = 2\))21 + 33 bytes \(\times 3\) = three compressed public keys53 = OP_3 (\(n = 3\))ae = OP_CHECKMULTISIGConfiguration: 2-of-3 multisig. WitnessScript size: \(1 + 3 \times 34 + 1 + 1 = 105\) bytes.
H4. 3-of-5 P2WSH:
P2SH 3-of-5 (from Chapter 7): scriptSig \(= 395\) bytes, scriptSig length varint \(= 3\) bytes (since \(395 > 252\)), total input \(= 32 + 4 + 3 + 395 + 4 = 438\) bytes, total tx (1-in-1-out with 23-byte P2SH output) \(= 4 + 1 + 438 + 1 + 32 + 4 = 480\) bytes (all non-witness), weight \(= 480 \times 4 = 1,920\) WU, vsize \(= 480\) vbytes.
Savings: \(480 - 194 = 286\) vbytes, a 59.6% reduction.
P1. Consider a 2-of-2 multisig P2WSH where Alice and Bob each hold one key. Under HASH160 (80-bit collision resistance), Alice could—in principle—run a birthday search at setup time: generate huge families of both innocent-looking 2-of-2 scripts and malicious single-key scripts (OP_CHECKSIG with only her key), hunting for any cross-pair with the same HASH160. After \(2^{80}\) operations she would expect to find such a pair, propose the innocent half to Bob, and later reveal the malicious twin, spending the funds unilaterally. (Against a fixed legitimate script, a second-preimage search would cost \(2^{160}\).) With SHA-256 (128-bit collision resistance), this attack requires \(2^{128}\) operations—far beyond any foreseeable computation. For P2WPKH, the "script" is implicit (a single key), so there is no second spending path for the attacker to exploit via collision.
P2. The fee savings come from the witness discount: witness bytes cost 1 WU while non-witness bytes cost 4 WU. The more data that moves to the witness, the greater the absolute and percentage savings. For P2WPKH, 107 bytes move to the witness (38% savings). For 2-of-3 P2WSH, 252 bytes move (49% savings). For 3-of-5 P2WSH, 395 bytes move (60% savings). In general, the savings approach 75% as the ratio of witness to non-witness data grows (the theoretical maximum when all transaction data is witness data, reducing weight by a factor of 4).
P3. In P2SH, the redeem script is pushed onto the stack as a single data element using a push opcode. Bitcoin Script limits any single push operation to 520 bytes, so the redeem script cannot exceed this. In P2WSH, the witnessScript is not pushed by a Script opcode—it is delivered as a separate witness stack item and handled by special-case consensus code (BIP 141). The consensus code imposes its own limit (10,000 bytes) rather than relying on Script's push-size constraint.
C1. The recipient of Output 0 may use a wallet that only supports P2SH addresses (a 3-address). The sender creates whatever output type the recipient's address specifies. Output 1 is the change output, sent back to the sender's own P2WSH address. Mixed output types are common during transition periods when not all wallets support the same address formats.
C2. 2-of-2 P2WSH:
2-of-2 P2SH:
Savings: \(302 - 150 = 152\) vbytes, a 50% reduction.
B1. In P2SH-P2WSH, the scriptSig would contain a push of the witness program (35 bytes: 1-byte push opcode + 34-byte witness program). The prevout scriptPubKey would be P2SH (23 bytes) instead of native P2WSH (34 bytes). The witness data would be identical.
The net non-witness change is \(+35\) bytes (scriptSig) \(-11\) bytes (shorter output) \(= +24\) non-witness bytes, adding \(24 \times 4 = 96\) WU. The weight rises from 758 to 854 WU and the vsize from 190 to \(\lceil 854/4 \rceil = 214\) vbytes.
B2. A 2-of-3 Taproot key-path spend using MuSig2 would produce a single 64-byte Schnorr signature in the witness. Witness: \(1 + 1 + 64 = 66\) bytes. Non-witness: \(94\) bytes. Total: \(94 + 2 + 66 = 162\) bytes. Weight: \(94 \times 3 + 162 = 444\) WU. vsize: \(\lceil 444/4 \rceil = 111\) vbytes.
That 111-vbyte figure uses a 1-input/1-output template; rebuilt with our specimen's two outputs it is ≈143 vbytes, so compared to the P2WSH specimen (190 vbytes) Taproot saves a further ≈25%—and reveals nothing about the multisig structure.