Part III · The SegWit Revolution Chapter 10

P2WSH: SegWit Script Hash

"The witnessScript is popped off the initial witness stack. SHA256 of the witnessScript must match the 32-byte witness program."BIP 141, Segregated Witness

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.

10.1The Specimen

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.

10.2P2WSH vs P2SH: Key Differences

P2WSH is the SegWit replacement for P2SH (Chapter 6), but with several important improvements:

PropertyP2SH (Ch. 6)P2WSH
Script hashHASH160 (20 bytes)SHA-256 (32 bytes)
Hash in scriptPubKeyYes (23 bytes)Yes (34 bytes)
ScriptSigSigs + redeem scriptEmpty (0 bytes)
Script locationscriptSigWitness
Weight per script byte4 WU1 WU
Script size limit520 bytes10,000 bytes
Signature digestLegacyBIP 143
Address format3… (Base58Check)bc1q… (bech32)

10.3The ScriptPubKey: SHA-256 Not HASH160

A P2WSH scriptPubKey is 34 bytes:

P2WSH ScriptPubKey (34 bytes)
HexOpcodeMeaning
00OP_0Witness version 0
20OP_PUSHBYTES_32Push 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.

Verify: WitnessScript → SHA-256 → Witness Program
WitnessScript (105 bytes — the 2-of-3 multisig):
Why SHA-256 Instead of HASH160?

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.

10.4The Witness: Script in the Discount Zone

Our specimen's witness contains four items:

Witness Data — Input 0 (252 bytes)
HexElementDetails
04Item count4 items
00Item 0 (dummy)Empty (CHECKMULTISIG bug)
47Item 1 length71 bytes
3044…2b01DER sig 1 + SIGHASH_ALL\(r\): 32 B, \(s\): 32 B
47Item 2 length71 bytes
3044…5501DER sig 2 + SIGHASH_ALL\(r\): 32 B, \(s\): 32 B
69Item 3 length105 bytes
5221…53aeWitnessScript2-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

10.5Validation

P2WSH validation proceeds in three steps:

  1. Script identification: the node sees OP_0 <32 bytes> in the scriptPubKey, identifies it as a version-0 witness program with a 32-byte program, and invokes P2WSH rules.
  2. WitnessScript verification: the last witness item (the witnessScript) is popped. Its SHA-256 hash must equal the 32-byte witness program.
  3. Script execution: the witnessScript is deserialized and executed against the remaining witness items as the initial stack.

For our 2-of-3 multisig specimen, the execution proceeds exactly as in Chapter 7:

P2WSH 2-of-3 Stack Execution
Step 0 / 7
Click Step to begin

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.

10.6Weight Savings: The Real Payoff

10.6.1Our Specimen's Weight

ComponentValue
Total size380 bytes
Marker + flag2 bytes
Witness data252 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
Fee50,000 sats
Fee rate\(50{,}000 \div 190 \approx 263\) sat/vbyte

10.6.2P2SH vs P2WSH: 2-of-3 Multisig

Both our Ch. 6 specimen (P2SH) and this specimen (P2WSH) perform 2-of-3 multisig. The comparison is dramatic:

MetricP2SH (Ch. 6)P2WSHSavings
Total size370 bytes380 bytes\(-10\) (larger!)
ScriptSig253 bytes0 bytes\(-253\)
Witness0 bytes252 bytes\(+252\)
Weight1,480 WU758 WU\(-\)722 (49%)
Virtual size370 vbytes190 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.

The Witness Discount Magnified

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.

10.7The 10,000-Byte Script Limit

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:

Individual Witness Items: 520 Bytes

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.

10.8What We Learned

P2WSH Exercises

Litmus (L) — P2WSH

  1. What is the size of a P2WSH scriptPubKey? How does it compare to P2SH and P2WPKH?
  2. How does BIP 141 distinguish P2WPKH from P2WSH when both use witness version 0?
  3. What hash function is used for the P2WSH witness program? Why not HASH160?
  4. What is the dummy item in the witness, and why is it required?
  5. What is the maximum size of a witnessScript in P2WSH?

Hands-On (H)

  1. From the specimen's hex, identify all witness items and compute the stripped size, weight, and vsize. Verify they match 380, 758, and 190.
  2. Verify the SHA-256 relationship: compute SHA-256 of the witnessScript 5221…53ae and confirm it matches the witness program 701a… c58d.
  3. Decode the witnessScript. How many public keys are present? What is the \(m\)-of-\(n\) configuration?
  4. Compute the weight and vsize of a 3-of-5 P2WSH multisig spend. Use 72-byte signatures and 33-byte compressed public keys. Compare to the P2SH equivalent from Chapter 7 (395-byte scriptSig).

Proofs and Reasoning (P)

  1. Why is collision resistance more important for P2WSH than P2WPKH? Describe a specific collision attack scenario against a hypothetical P2WSH that used HASH160.
  2. Explain why P2WSH's fee savings percentage increases with the complexity of the script (more signatures, larger scripts).
  3. Why is the witnessScript not subject to the 520-byte data push limit?

Connections (C)

  1. Our specimen sends one output to a P2SH address (3NL8…) and one to P2WSH (bc1q…). Why might a wallet produce mixed output types?
  2. Lightning Network funding transactions use 2-of-2 P2WSH multisig. Compute the weight savings compared to 2-of-2 P2SH multisig.

Bridge (B)

  1. How would this transaction differ if it used P2SH-P2WSH (Chapter 11)? What additional data would appear in the scriptSig?
  2. Taproot's key-path spend (Chapter 12) can represent any multisig as a single signature via MuSig2. How would a 2-of-3 Taproot spend compare to our P2WSH specimen in weight?

Solutions

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:

Configuration: 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.

← Ch. 9 Ch. 11 →