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.

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!)
ScriptSig254 bytes0 bytes\(-254\)
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 bare 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

Wrapped SegWit: The Backward-Compatible Bridge

"Triggered when a scriptPubKey is a P2SH script, and the BIP16 redeemScript pushed in the scriptSig is exactly a push of a version byte plus a push of a witness program."—BIP 141, Segregated Witness

SegWit activated on August 24, 2017. The protocol was ready. The wallets were not.

Native SegWit outputs use bech32 addresses (bc1q…), but in 2017 most wallets and exchanges could only send to legacy addresses—1… (P2PKH) or 3… (P2SH). A user who generated a bech32 address and asked Coinbase to withdraw to it would get an error: "invalid address."

The solution was elegant. Wrap the SegWit witness program inside a P2SH script. The output looks like any other P2SH output (a 3-address), but when spent, the P2SH redeem script turns out to be a witness program, triggering SegWit validation. Legacy wallets can send to it without knowing SegWit exists. Only the spender needs SegWit awareness.

This chapter covers both flavors:

10.9Why Wrapping Was Necessary

SegWit's designers faced a deployment dilemma. Native SegWit required senders to understand bech32 addresses, but Bitcoin's ecosystem had hundreds of wallets, exchanges, and payment processors. Updating them all simultaneously was impossible. BIP 141 solved this with a two-pronged strategy:

  1. Native witness programs (bc1q…): optimal efficiency, but requires sender support.
  2. P2SH-wrapped witness programs (3…): slightly less efficient, but any wallet that supports P2SH (since 2012) can send to them.

In practice, wrapped SegWit dominated from 2017 through 2019. Exchanges like Coinbase did not support sending to bech32 addresses until 2020. Even today, some services still generate 3-addresses for SegWit wallets to maximize compatibility.

10.10P2SH-P2WPKH: Revisiting Our Chapter 8 Specimen

Our Chapter 8 specimen—the first SegWit transaction ever confirmed (block 481,824)—is a P2SH-P2WPKH spend. Let us now examine exactly how the wrapping works.

10.10.1The Funding Output

When someone sends to a P2SH-P2WPKH address, they create a standard P2SH output:

Funding ScriptPubKey (23 bytes)
HexOpcodeMeaning
a9OP_HASH160Hash the top stack item
14OP_PUSHBYTES_20Push next 20 bytes
(20 bytes)(data)HASH160 of the redeem script
87OP_EQUALCheck equality

This is identical to any P2SH output. The sender does not know—and does not need to know—that the redeem script is a witness program.

10.10.2The Redeem Script (Witness Program)

The redeem script hidden inside this P2SH is simply a witness program:

Redeem Script = Witness Program (22 bytes)
HexOpcodeMeaning
00OP_0Witness version 0
14OP_PUSHBYTES_20Push next 20 bytes
(20 bytes)(data)HASH160 of the public key

This 22-byte script is the bridge: it satisfies P2SH (it is the preimage of the script hash) and it matches the pattern for a version-0, 20-byte witness program, triggering P2WPKH rules.

10.10.3The ScriptSig: No Longer Empty

Unlike native P2WPKH (Chapter 9), the scriptSig is not empty. It contains exactly one item: a push of the 22-byte redeem script:

ScriptSig (23 bytes)
HexOpcodeMeaning
16OP_PUSHBYTES_22Push next 22 bytes
0014…(data)The 22-byte witness program

This 23-byte scriptSig is the only additional cost of wrapping. The witness data (signature + public key) is identical to native P2WPKH.

10.10.4Two-Stage Validation

Validation proceeds in two stages:

  1. P2SH stage: the node hashes the scriptSig data with HASH160 and verifies it matches the 20-byte hash in the scriptPubKey. If it matches, the redeem script is deserialized.
  2. SegWit stage: the deserialized redeem script is OP_0 <20 bytes>—a version-0, 20-byte witness program. The node invokes P2WPKH rules: verify the witness signature against the public key whose HASH160 matches the witness program.
The Nesting Trick

BIP 141 defines that a witness program can appear in two places: directly in a scriptPubKey (native) or as a P2SH redeem script (wrapped). The node checks both locations. If the redeem script after P2SH evaluation matches the witness program pattern, SegWit kicks in automatically. This is why only one level of wrapping is allowed—BIP 141 explicitly forbids P2SH-P2SH-P2WPKH or any deeper nesting.

10.11P2SH-P2WSH: Wrapping Arbitrary Scripts

The same wrapping technique applies to P2WSH. For a 2-of-3 multisig:

P2SH-P2WSH Redeem Script = Witness Program (34 bytes)
HexOpcodeMeaning
00OP_0Witness version 0
20OP_PUSHBYTES_32Push next 32 bytes
(32 bytes)(data)SHA-256 of the witnessScript

The scriptSig is 35 bytes: OP_PUSHBYTES_34 (0x22) followed by the 34-byte witness program. The witness data is identical to native P2WSH.

Reduced Security

BIP 141 notes that P2SH-P2WSH has reduced security compared to native P2WSH. The funding output commits to a 20-byte HASH160 of the redeem script (80 bits of collision resistance), not the 32-byte SHA-256 used in native P2WSH (128 bits). For high-value multisig, native P2WSH is strongly preferred.

10.12The Cost of Compatibility

Wrapping adds exactly one cost: the scriptSig bytes, which count as non-witness data at 4 WU each.

TypeScriptSigExtra WUExtra vbytes
P2SH-P2WPKH23 bytes\(23 \times 4 = 92\)23
P2SH-P2WSH35 bytes\(35 \times 4 = 140\)35

10.12.1Complete Comparison: 1-Input, 2-Output

The following table compares all output types for a single-key (P2PKH family) and a 2-of-3 multisig (P2SH family) transaction, each with 1 input and 2 outputs. Signatures are assumed to be 72 bytes (worst-case DER).

Single-key (1-in-2-out)SizeWeightvsizevs Legacy
P2PKH (legacy)226904226
P2SH-P2WPKH (wrapped)248662166\(-27%\)
P2WPKH (native)223562141\(-38%\)

Outputs are type-matched: P2PKH outputs (34 B) for legacy, P2SH (32 B) for wrapped, P2WPKH (31 B) for native. 72-byte worst-case DER signatures throughout.

2-of-3 multisig (1-in-2-out)SizeWeightvsizevs Legacy
P2SH multisig (legacy)3701,480370
P2SH-P2WSH (wrapped)406856214\(-42%\)
P2WSH (native)393804201\(-46%\)

Legacy baseline from Ch. 6 specimen. Wrapped uses P2SH outputs (32 B); native uses P2WSH outputs (43 B).

The pattern is clear: wrapping captures most of SegWit's fee savings. The wrapper's cost is exactly its scriptSig size: 23 vbytes for P2SH-P2WPKH, 35 vbytes for P2SH-P2WSH (see exercise P1). Compared to the total savings over legacy, this overhead is modest.

Most Savings Come From the Witness Discount

The wrapped-vs-native gap (23 or 35 vbytes) is small compared to the legacy-vs-wrapped gap (60 or 156 vbytes). This is because the dominant cost reduction comes from moving signatures to the witness at 1 WU per byte instead of 4. The scriptSig wrapper is a fixed overhead that becomes proportionally smaller as transactions grow more complex.

10.13Address Generation

A P2SH-P2WPKH address is generated in three steps:

  1. Compute the public key hash: \(h = \text{HASH160}(\text{pubkey})\) (20 bytes).
  2. Build the witness program: 0x0014 \(\|\) \(h\) (22 bytes).
  3. Compute the P2SH address: \(\text{Base58Check}(\texttt{0x05} \| \text{HASH160}(\text{witness program}))\).

The result is a standard 3-address. No external observer can distinguish it from a regular P2SH multisig address until the output is spent and the 22-byte redeem script is revealed.

For P2SH-P2WSH, step 2 uses 0x0020 \(\|\) \(\text{SHA-256}(\text{witnessScript})\) (34 bytes), and step 3 hashes this 34-byte witness program.

10.14The Timeline of Adoption

DateMilestone
Aug 2017SegWit activates (block 481,824). Wrapped SegWit is the only practical option.
Feb 2018Bitcoin Core 0.16.0 adds bech32 support. Major exchanges begin SegWit rollout.
Jun 2020Bitcoin Core 0.20.0 makes P2WPKH the default address type.
2020-2021Major exchanges (Coinbase, Kraken, Gemini) add bech32 send support.
2023-2024Native SegWit (bech32) dominates; wrapped SegWit usage declines.

Wrapped SegWit served its purpose: it bridged the three-year gap between protocol readiness and ecosystem readiness. By 2024, it was largely superseded by native SegWit and Taproot.

10.15What We Learned

10.15.1Looking Ahead

This chapter concludes Part III. We have traced the complete SegWit story: the motivation (Chapter 8), native single-key (Chapter 9), native scripts (Chapter 10), and the backward-compatible bridge (this chapter). Part IV turns to Taproot—the next major upgrade, activated in November 2021—which unifies all output types under a single 34-byte scriptPubKey format using Schnorr signatures and Merklized Abstract Syntax Trees (MAST).

Exercises

Litmus (L)

  1. What is the size of a P2SH-P2WPKH scriptSig? What does it contain?
  2. Why can legacy wallets send to P2SH-wrapped SegWit addresses but not to native SegWit addresses?
  3. How does a node determine that a P2SH redeem script is a witness program?
  4. Why is only one level of P2SH wrapping allowed for SegWit?
  5. What is the collision resistance difference between P2SH-P2WSH and native P2WSH?

Hands-On (H)

  1. Revisit the Chapter 8 specimen. Identify the 23-byte scriptSig and verify that HASH160 of its payload matches the scriptPubKey's 20-byte hash.
  2. Compute the weight and vsize of a P2SH-P2WPKH transaction with 2 inputs and 3 outputs (all P2SH-P2WPKH). Use 72-byte signatures and 33-byte compressed public keys.
  3. Compute the P2SH address for a P2SH-P2WPKH output given the public key hash 751e76e8199196d454941c45d1b3a323f1433bd6 (from BIP 141's test vector).

Proofs and Reasoning (P)

  1. Prove that the vsize overhead of P2SH-P2WPKH versus native P2WPKH equals exactly the scriptSig length in bytes, regardless of the number of inputs or outputs.
  2. Explain why P2SH-P2WSH has 80 bits of collision resistance while native P2WSH has 128 bits, even though both ultimately verify a SHA-256 hash of the witnessScript.

Connections (C)

  1. Lightning Network channel funding transactions originally used P2SH-P2WSH. Why was this a reasonable choice in 2017–2018? Why did most implementations switch to native P2WSH?
  2. Our Chapter 10 specimen sends one output to a P2SH address. Could that P2SH output be a P2SH-P2WSH? How would you determine this from the blockchain?

Bridge (B)

  1. Taproot (Chapter 12) uses bech32m addresses (bc1p…), not P2SH wrapping. Why was the P2SH bridge not repeated for Taproot?
  2. How would you migrate a wallet from P2SH-P2WPKH to native P2WPKH? What information does the user need, and what changes on-chain?

Solutions

L1. 23 bytes. It contains a single push: OP_PUSHBYTES_22 (0x16) followed by the 22-byte witness program (0014 + 20-byte key hash).

L2. Legacy wallets understand P2SH addresses (3…), valid since BIP 16 activation in 2012. The sender constructs a standard P2SH output without knowing the redeem script's contents. Native SegWit uses bech32 addresses (bc1q…), which legacy wallets do not recognize as valid.

L3. After the P2SH hash check succeeds, the node deserializes the redeem script and checks whether it matches the witness program pattern: a 1-byte version push (OP_0 through OP_16) followed by a direct data push between 2 and 40 bytes. If it does, SegWit rules are triggered.

L4. BIP 141 explicitly defines only two locations where a witness program is recognized: (1) directly in a scriptPubKey, or (2) as a BIP 16 P2SH redeem script. Multiple levels of wrapping (P2SH-P2SH-P2WPKH) would create ambiguity and complexity without any benefit—one level of wrapping already provides full backward compatibility.

L5. P2SH-P2WSH: the funding output uses HASH160 (20 bytes, 80 bits of collision resistance) to commit to the 34-byte witness program. Native P2WSH: the funding output uses the 32-byte SHA-256 directly (128 bits of collision resistance). The 48-bit gap is significant—\(2^{80}\) operations are theoretically within reach, while \(2^{128}\) is not.

H1. From the Chapter 8 specimen, the scriptSig is at the input's scriptSig field. The payload after the 0x16 push opcode is the 22-byte witness program: 0014… (20-byte key hash). Computing HASH160 of this 22-byte value should yield the 20-byte hash in the prevout scriptPubKey (a914…87).

H2. 2-input, 3-output P2SH-P2WPKH:

H3.

  1. Witness program: 0014751e76e8199196d454941c45d1b3a323f1433bd6 (22 bytes).
  2. HASH160 of the witness program: compute SHA-256, then RIPEMD-160. Per BIP 141's test vectors, this yields bcfeb728b584253d5f3f70bcb780e9ef218a68f4.
  3. P2SH address: Base58Check encode 05bcfeb728b584253d5f3f70bcb780e9ef218a68f4 3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN.

P1. Consider \(n\) inputs and \(k\) outputs. In native P2WPKH, each input has a 0-byte scriptSig (1-byte length varint). In P2SH-P2WPKH, each input has a 23-byte scriptSig (1-byte length varint, since \(23 < 253\)). The output data is identical. The witness data is identical. The only difference per input is \(+23\) non-witness bytes. Each non-witness byte costs exactly 4 WU (it appears in both the stripped size \(\times 3\) and total size \(\times 1\) terms). So the total weight increase is \(23n \times 4 = 92n\) WU, and the vsize increase is \(\lceil 92n/4 \rceil = 23n\) vbytes. For a single input, this is exactly 23 vbytes—the scriptSig length. The proof generalizes: the overhead per input is always the scriptSig byte count.

P2. In P2SH-P2WSH, the funding output contains OP_HASH160 <20> OP_EQUAL. An attacker performing a collision attack targets this 20-byte HASH160, which has only \(2^{80}\) collision resistance. If Alice and Bob create a 2-of-2 P2SH-P2WSH, Alice could search for a different 34-byte witness program (containing a different witnessScript) that produces the same HASH160. She needs \(2^{80}\) operations.

In native P2WSH, the funding output contains the 32-byte SHA-256 directly. A collision attack now targets the SHA-256 with \(2^{128}\) collision resistance. Even if the attacker finds a witness program collision, it must also be a valid witness program (starting with 0020), further constraining the search.

The key insight: the witness is verified against SHA-256 in both cases, but the funding commitment uses a weaker hash in the wrapped version. The attack occurs before spending, when the attacker substitutes a different script at the P2SH commitment layer.

C1. In 2017–2018, most counterparties (exchanges, wallets) could only send to P2SH addresses. Lightning implementations needed to accept channel funding from these counterparties, so P2SH-P2WSH was the practical choice. As bech32 support became widespread (2019–2020), implementations switched to native P2WSH for the improved collision resistance and slightly lower fees. The BOLT specifications now recommend native P2WSH for channel funding.

C2. From the blockchain alone, you cannot determine whether a P2SH output is P2SH-P2WSH, P2SH-P2WPKH, or plain P2SH multisig. All three have identical scriptPubKeys (a914…87). The redeem script is only revealed when the output is spent—at that point, the scriptSig reveals whether it is a 22-byte witness program (P2SH-P2WPKH), 34-byte witness program (P2SH-P2WSH), or a full multisig script (plain P2SH). Until spent, the output type is hidden. This is a privacy feature of P2SH.

B1. By November 2021 (Taproot activation), bech32/bech32m support was widespread. Major exchanges had added bech32 send support during 2020–2021, and Bitcoin Core had made P2WPKH the default address type since version 0.20.0 (June 2020). The ecosystem no longer needed a backward-compatible bridge. Additionally, wrapping Taproot in P2SH would negate some of its privacy benefits: Taproot aims to make all output types look identical, but a 3-address immediately identifies the output as P2SH.

B2. Migration is simple: the wallet generates a new native P2WPKH address (bech32) using the same key pair and sends funds from the old P2SH-P2WPKH address to the new one. The user needs only their private key—the public key hash is derived identically in both cases. On-chain, a transaction moves funds from a 3-address to a bc1q-address. The key pair does not change; only the address encoding and spending mechanism differ. Future receives should use the new bech32 address.

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—search for a different script that hashes to the same HASH160 as the legitimate 2-of-2 script. After \(2^{80}\) operations, she might find a single-key script (OP_CHECKSIG with only her key) with an identical hash. She could replace the legitimate script with her malicious one, spending the funds unilaterally. 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.

Compared to our P2WSH specimen (190 vbytes), Taproot saves an additional 42%—and reveals nothing about the multisig structure.

← Ch. 9 Ch. 11 →