Introduction to P2SH (Pay-to-Script-Hash)

Overview

P2SH (Pay-to-Script-Hash) is a Bitcoin address format introduced in BIP16 that enables payments to the hash of a script rather than the hash of a public key. These addresses begin with 3 on mainnet and allow complex spending conditions to be hidden until the funds are spent. P2SH shifted the responsibility of providing the redeem script from the sender to the recipient, enabling advanced features like multisig without requiring sender awareness of the underlying complexity.

How It Works

P2SH addresses are derived from a redeem script through the following process:

The following diagram shows the anatomy of a P2SH address:
P2SH Address Anatomy Script Hash Generation Redeem Script Variable length (e.g. multisig) SHA-256 RIPEMD160 Script Hash (HASH160) 20 bytes Checksum Generation Version 0x05 + Script Hash 20 bytes Version + Script Hash (21 bytes) SHA256(SHA256(...)) Checksum First 4 bytes Version 1 byte Script Hash (HASH160) 20 bytes Checksum 4 bytes 25 bytes total Base58Check Encode P2SH Address 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
  1. Create a redeem script defining the spending conditions (e.g., multisig, timelock, or custom logic).
  2. Apply SHA-256 hashing to the redeem script.
  3. Apply RIPEMD-160 hashing to the SHA-256 result, producing a 160-bit hash (20 bytes).
  4. Add a version byte prefix (0x05 for mainnet, 0xC4 for testnet).
  5. Calculate a checksum using double SHA-256 and append the first 4 bytes.
  6. Encode the result using Base58Check encoding.

The key innovation of P2SH is that the sender only needs to know the script hash, not the full script. The recipient provides the complete redeem script when spending the funds, and the network verifies that the script hashes to the expected value.

Redeem Scripts

The redeem script defines the actual spending conditions. Common redeem script types include:

Multisig (M-of-N)

Requires M signatures from N possible public keys.

The following example shows a 2 of 3 signatures script:
plaintext
OP_2
<pubkey1>
<pubkey2>
<pubkey3>
OP_3
OP_CHECKMULTISIG

Timelock

Funds can only be spent after a specific time or block height.

The following example shows a specific time or block height script:
plaintext
<expiry_time>
OP_CHECKLOCKTIMEVERIFY
OP_DROP
<pubkey>
OP_CHECKSIG

Hash Lock

Requires knowledge of a preimage that hashes to a specific value.

The following example shows a hash lock script:
plaintext
OP_HASH160
<hash>
OP_EQUAL

Nested SegWit (P2SH-P2WPKH)

Wraps a SegWit script inside P2SH for backward compatibility.

The following example shows a nested SegWit script:
plaintext
OP_0
<20 bytes public key hash>

Security Considerations

P2SH provides security through script hashing. The actual spending conditions remain hidden until the funds are spent, offering some privacy benefits. However, once spent, the full redeem script is revealed on the blockchain.

The 20 bytes script hash provides 160-bit collision resistance. While theoretically possible, finding a collision (a different script that produces the same hash) is computationally infeasible with current technology.

P2SH scripts have a size limit of 520 bytes for the redeem script. This limits the complexity of spending conditions that can be encoded. For more complex scripts, P2WSH (Pay-to-Witness-Script-Hash) with its larger script allowance may be more appropriate.

Address Format

P2SH addresses use Base58Check encoding, similar to P2PKH but with a different version byte:

  • Mainnet: Addresses start with 3.
  • Testnet: Addresses start with 2.
  • Regtest: Addresses start with 2.

The Base58Check encoding provides error detection through a 4 bytes checksum and excludes visually ambiguous characters.