TeachMeBitcoin

Pay-to-Script-Hash Mechanics (P2SH — BIP 16)

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

Pay-to-Script-Hash Mechanics (P2SH — BIP 16)

While native multisig works perfectly inside Bitcoin’s virtual machine, deploying raw multisig scripts directly into transaction outputs introduced massive real-world problems.

To solve this, developers activated Pay-to-Script-Hash (P2SH) via a soft fork in 2012 (formalized in BIP 16).


The Problems with Raw Native Multisig

Before P2SH, if a merchant wanted to use a 2-of-3 multisig wallet for safety, anyone paying that merchant had to construct a massive, non-standard transaction output:

OP_2 <PubKey_A> <PubKey_B> <PubKey_C> OP_3 OP_CHECKMULTISIG

This model had three severe flaws:

  1. Sender Burden: Senders had to pay significantly higher transaction fees because the output (scriptPubKey) was massive, and fee costs are determined by transaction data size.

  2. Inconvenience: The sender had to know all three of the receiver’s public keys and understand the exact script layout just to send a basic payment.

  3. UTXO Bloat: Because these outputs contained large public keys, they took up a massive amount of space inside full nodes' RAM-cached chainstate databases.


The Solution: Pay-to-Script-Hash (P2SH)

P2SH shifts the burden of complex scripts from the sender to the receiver.

Instead of sending coins to a massive, complex lock, the sender locks the coins to a simple 20-byte cryptographic hash of the spending script (which we call the Redeem Script).

OP_HASH160 <20-Byte-RedeemScriptHash> OP_EQUAL

 NATIVE MULTISIG (SENDER PAYS FOR BLOAT)
┌────────────────────────────────────────────────────────────────────────┐
│ scriptPubKey: OP_2 <PubKeyA> <PubKeyB> <PubKeyC> OP_3 OP_CHECKMULTISIG │
└───────────────────────────────────┬────────────────────────────────────┘
 │ (Huge byte footprint in output)
 ▼
 P2SH (RECEIVER PAYS FOR BLOAT)
┌────────────────────────────────────────────────────────────────────────┐
│ scriptPubKey: OP_HASH160 <RedeemScriptHash> OP_EQUAL │
└───────────────────────────────────┬────────────────────────────────────┘
 │ (Tiny, standard output footprint)
 ▼

How P2SH Validation Works (Two-Step Execution)

When the receiver wants to spend the P2SH output, they must present the raw signatures AND the full serialized Redeem Script inside their input’s scriptSig:

A validating full node executes the verification process in two distinct, sequential phases:

 P2SH VALIDATION CYCLE
┌────────────────────────────────────────────────────────────────────────┐
│ PHASE 1: THE HASH CHECK │
├────────────────────────────────────────────────────────────────────────┤
│ • Node executes: OP_HASH160 <RedeemScriptHash> OP_EQUAL │
│ • It hashes the Serialized_RedeemScript from the spender. │
│ • Checks if Hash(RedeemScript) == RedeemScriptHash in the output. │
└───────────────────────────────────┬────────────────────────────────────┘
 │
 ├───► [FAIL] ──► Tx Rejected
 │
 ▼ [PASS]
┌────────────────────────────────────────────────────────────────────────┐
│ PHASE 2: REDEEM SCRIPT EXECUTION │
├────────────────────────────────────────────────────────────────────────┤
│ • Node deserializes the Serialized_RedeemScript bytes back into Opcodes│
│ • Executes the script: OP_2 <PubA> <PubB> <PubC> OP_3 OP_CHECKMULTISIG │
│ • Runs this script using the remaining signatures: [0, Sig_A, Sig_C] │
└───────────────────────────────────┬────────────────────────────────────┘
 │
 ▼
 Is Final Execution = 1?
 [YES] ──► Spend Approved (Valid)
 [NO] ──► Transaction Rejected (Invalid)

Key Benefits of P2SH

☕ 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!