Part III · The SegWit Revolution Chapter 11

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:

11.1Why 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.

11.2P2SH-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.

11.2.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.

11.2.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.

11.2.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.

11.2.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.
P2SH-P2WPKH Two-Stage Validation
Step 0 / 8
Stage 1: P2SH Hash Check
Click Step to begin
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.

11.3P2SH-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.

11.4The 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

11.4.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)3711,484371
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 (25 or 13 vbytes in the tables above) is small compared to the legacy-vs-wrapped gap (60 or 157 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.

11.5Address 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.

11.6The 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.

11.7What We Learned

11.7.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 05bcfeb728b584253d5f3f70bcb780e9ef218a68f43JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN.

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.

← Ch. 10 Ch. 12 →