TeachMeBitcoin

P2SH-P2WPKH Nested SegWit - Full Execution

From TeachMeBitcoin, the free encyclopedia Reading time: 2 min

7. P2SH-P2WPKH Nested SegWit — Full Execution

Overview

P2SH-P2WPKH is a backward-compatible "nested SegWit" format that wraps a P2WPKH witness program inside a P2SH envelope. This allows legacy wallets (which don't understand native SegWit bc1q addresses) to send funds to a SegWit-capable receiver. The sender sees a regular 3... address; the receiver gets SegWit benefits.

This format, defined in BIP 141 (section on P2SH compatibility), was a transitional mechanism and is still widely used today.

Script Structure

The redeemScript for P2SH-P2WPKH is a P2WPKH scriptPubKey:

redeemScript = OP_0 <20-byte HASH160(pubkey)>
             = 00 14 <20 bytes>    (22 bytes total)

Locking script (scriptPubKey) — standard P2SH wrapping:

OP_HASH160 <HASH160(redeemScript)> OP_EQUAL

Unlocking script (scriptSig):

<serialized redeemScript>

Note: The scriptSig contains ONLY the serialized redeemScript — it is a single data push.

Witness field:

02
<signature>
<pubkey>

Full Three-Layer Execution

Layer 1: P2SH validation

scriptSig: PUSH(redeemScript)
scriptPubKey: OP_HASH160 <hash> OP_EQUAL

Execution:
HASH160(redeemScript) == stored hash? → TRUE

Stack: [1]

Layer 2: SegWit witness program detection

After P2SH validation, interpreter detects that the redeemScript
is a valid witness program: OP_0 <20-byte program>

This triggers SegWit execution rules.
scriptSig must contain only a single push of the redeemScript.
If scriptSig contains anything else → INVALID

Layer 3: Witness execution (P2WPKH)

Witness: [<sig>, <pubkey>]
Implicit script: OP_DUP OP_HASH160 <20-byte program> OP_EQUALVERIFY OP_CHECKSIG

Result: [1] → VALID

Address Derivation

def pubkey_to_p2sh_p2wpkh_address(pubkey_hex: str) -> str:
    pubkey_bytes = bytes.fromhex(pubkey_hex)
    # Step 1: Build inner witness program
    keyhash = hash160(pubkey_bytes)                    # RIPEMD160(SHA256(pubkey))
    redeem_script = bytes([0x00, 0x14]) + keyhash      # OP_0 PUSH20 <keyhash>
    # Step 2: P2SH-hash the redeemScript
    script_hash = hash160(redeem_script)               # RIPEMD160(SHA256(redeemScript))
    # Step 3: Version byte 0x05 for P2SH mainnet
    payload = bytes([0x05]) + script_hash
    checksum = sha256d(payload)[:4]
    return base58.b58encode(payload + checksum).decode()

Weight Analysis

P2SH-P2WPKH input breakdown:
  Non-witness: outpoint(36) + scriptSig_len(1) + redeemScript_push(23) + sequence(4) = 64 bytes × 4 = 256 WU
  Witness: sig(72) + pubkey(33) + overhead(3) = 108 bytes × 1 = 108 WU

vs native P2WPKH: ≈ 271 WU ≈ 67.75 vbytes

The nested format costs ~34% more than native SegWit, but remains ~40% cheaper than legacy P2PKH, making it a valuable transitional format.

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!