P2SH (Pay-to-Script-Hash)
Bloquea fondos al hash de un script. El receptor define las condiciones, el emisor solo necesita la dirección.
El concepto
P2SH (Pay-to-Script-Hash), definido en BIP 16, introdujo una idea elegante: en vez de poner el script de bloqueo completo en el output, se pone solo su hash. El script completo (llamado redeemScript) se revela al gastar.
Las direcciones P2SH empiezan por "3" (como 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy).
El problema que resuelve
Imagina un multisig 2-de-3. El script de bloqueo sería largo: OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG
Son ~105 bytes solo para el scriptPubKey. El emisor tendría que conocer todas las claves públicas y construir este script.
Con P2SH:
- El receptor construye el script complejo
- Calcula su hash
- Da al emisor una dirección corta basada en ese hash
- El emisor envía a esa dirección sin conocer el script
El script de bloqueo (scriptPubKey)
OP_HASH160 <20 bytes: scriptHash> OP_EQUAL
En hexadecimal: a914<20 bytes scriptHash>87
Solo 23 bytes, independientemente de lo complejo que sea el redeemScript.
El script de desbloqueo (scriptSig)
<datos que satisfacen el redeemScript> <redeemScript>
El scriptSig incluye:
- Los datos necesarios para satisfacer el redeemScript (firmas, etc.)
- El redeemScript completo
Ejecución
La validación ocurre en dos fases:
Fase 1: Verificar el hash
Push <datos> (ignorados en esta fase) Push <redeemScript> OP_HASH160 Pila: [datos..., hash(redeemScript)] Push <scriptHash> Pila: [datos..., hash(redeemScript), expectedHash] OP_EQUAL ¿hash(redeemScript) == expectedHash? Pila: [datos..., TRUE/FALSE]
Si el hash no coincide, falla inmediatamente.
Fase 2: Ejecutar el redeemScript
Si la fase 1 pasa (el hash coincide), el redeemScript se "deserializa" y ejecuta con los datos proporcionados.
Es como si el redeemScript fuera el scriptPubKey original, y los datos anteriores fueran el scriptSig.
Ejemplo: P2SH-Multisig
RedeemScript para 2-de-3: OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG
Para gastar, el scriptSig sería: OP_0 <sig1> <sig2> <redeemScript>
(El OP_0 al inicio es por un bug histórico en OP_CHECKMULTISIG que consume un elemento extra de la pila.)
El receptor calcula: scriptHash = HASH160(redeemScript)
Y da al emisor una dirección derivada de ese hash.
P2SH-P2WPKH: SegWit envuelto
Cuando SegWit se activó, muchas wallets y servicios no lo soportaban. P2SH permitió una transición gradual:
El redeemScript es simplemente: OP_0 <20 bytes pubKeyHash>
Esto indica un witness program versión 0. El nodo reconoce que debe buscar los datos de firma en el witness, no en el scriptSig.
Desde fuera, parece una transacción P2SH normal (dirección empieza por 3). Pero internamente usa SegWit.
Esto permitió a usuarios con wallets SegWit recibir de servicios que solo soportaban direcciones legacy o P2SH.
Limitaciones de P2SH
Tamaño del redeemScript
El redeemScript completo debe caber en el scriptSig, que tiene límites de tamaño. Para scripts muy complejos, esto puede ser un problema.
Revelación completa
Al gastar, revelas TODO el redeemScript. Si tienes un esquema con múltiples condiciones alternativas, todas se revelan aunque solo uses una.
Taproot resuelve esto con MAST: solo revelas la rama que usas.
Fees
El redeemScript va en el scriptSig, que cuenta como datos "base" (4 WU/byte). P2WSH (SegWit nativo) pone el script en el witness (1 WU/byte), resultando en fees menores.
Direcciones P2SH
Las direcciones P2SH usan Base58Check con prefijo 0x05 para mainnet:
- scriptHash (20 bytes)
- Prefijo: 0x05
- Checksum: SHA256(SHA256(...))[0:4]
- Concatenar y codificar en Base58
El resultado empieza por "3".
Cuándo usar P2SH hoy
- P2SH-P2WPKH: si necesitas compatibilidad con sistemas que no soportan bc1q
- Multisig legacy: aunque P2WSH es preferible para nuevos setups
- Compatibilidad con contratos existentes
Para nuevos usos, SegWit nativo (P2WSH) o Taproot son preferibles.