Una introducción a los distintas formas de pago que existen en Bitcoin y como han ido evolucionando, junto con los scripts y direcciones correspondientes. Un repaso por P2PK, P2PKH, P2SH, P2WPKH, P2WSH, P2SH-P2WPKH, y P2TR.
Pay To Public Key (P2PK)
Los primeros pagos de Bitcoin se hacían directo a public keys (“Pay to Public Key”, o “P2PK”). Si Maria le quería pagar a Juan, entonces Juan debía pasarle su public key (<juan_pubkey>), y Maria creaba una Tx con este locking script en el output:
<juan_pubkey> OP_CHECKSIG
Los outputs son donde se “reciben” y bloquean los BTC, mediante un script de bloqueo (scriptPubKey). Los inputs son donde se gastan los BTC, usando un script de desbloqueo (scriptSig). Podés leer éste artículo y éste otro articulo para entender mejor qué son los inputs y los outputs.
Cuando alguien envía una transacción que gaste un output, los nodos combinan el scriptSig del input + scriptPubKey del output, y lo ejecutan como un script combinado. Para que el gasto sea válido, la ejecución debe dar TRUE (un valor distinto de 0)

Al momento de gastarlo, Juan sólo tiene que poner su signature en el unlocking script del input que gasta esos fondos. El script final que ejecutan los nodos es:
<juan_signature> <juan_pubkey> OP_CHECKSIG
Que sólo da TRUE cuando la signature es válida para la public key de Juan (y otros datos de la transacción según el sighash type).




P2PK es simple pero tiene varios problemas. El primero es que la public key consiste en 65 bytes (130 caracteres) en su forma no comprimida. Esto hace que sea difícil de transmitir y cualquier error podría pasar inadvertido porque las public keys no tienen chequeo de errores.
Para simplificarlo, bitcoin core permitía conectarse con el receptor de los fondos vía IP y de esa forma se transmitía la clave pública del receptor. El problema era que ambos nodos debían estar online al mismo tiempo. Ahí es donde surge “Pay To Public Key Hash”, o P2PKH.
Pay To Public Key Hash (P2PKH)
En P2PKH, el pago se hace al hash de una public key (PKH) en vez de una public key. Sería algo así:
“Pagale a este hash (commitment), y cuando quiera gastar los fondos demostraré que ese hash se hizo con mi public key, y también proveeré una signature válida para la public key”
El output era un poco más complejo y se veía de la siguiente manera:
OP_DUP OP_HASH160 <pkh> OP_EQUALVERIFY OP_CHECKSIG
Para gastarlo ya no alcanza con sólo una signature, si no que también hay que agregar la pub key con la que fue creado el hash. El script de desbloqueo se ve así:
<signature> <pubkey>
Los nodos juntan el script de desbloqueo y el de bloqueo, y lo ejecutan completo:
<signature> <pubkey> OP_DUP OP_HASH160 <pubkey_hash> OP_EQUAL OP_CHECKSIG
Que sólo da TRUE si el hash de la pubkey es igual al pubkey_hash del output, y si la signature también es válida.
Los hashes de las public keys, codificados en base58, dieron lugar a las primeras addresses de Bitcoin. En el caso de P2PKH, los addresses se codifican con el prefijo 0 (0x00), lo que resulta en direcciones comenzando con “1”

Las principal ventaja de P2PKH vs P2PK es que el hash ocupa 20 bytes vs 65 bytes de las public keys. Y los addresses (codificación base58 del hash) tienen chequeo de errores incorporado y son más legibles para los humanos.
P2PKH tiene otra ventaja de seguridad respecto a P2PK, y es que si se lograra romper ECDSA, los fondos P2PK serían robados inmediatamente porque las pub keys están a la vista de todos. Los addresses de P2PKH, en cambio, están protegidos por un doble hash (sha256 y RIPEMD160).
Multisig y scripts más complejos
Ahora supongamos que Juan quiere que María le envíe 1BTC, pero además quiere que se lo deposite en una multisig 1 de 2 con su amigo Pedro. María podría crear un output de 1 BTC y bloquearlo en un script así:
OP_1 <pubkey_juan> <pubkey_pedro> OP_2 OP_CHECKMULTISIG
Tanto Juan como Pedro podrían gastar ese BTC enviando su propia signature, ya que en una multisig 1 de 2 alcanza con sólo una signature válida. Acá hay un ejemplo real de este caso: https://mempool.space/tx/60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1…
Ver detalles del primer output (imagen):

El problema de este formato es que Juan debería pasarle el script multisig a María, y María debería usar una wallet que soporte ese tipo de scripts. Por otro lado, no hay chequeo de errores en el script y María debería pagar la fee por todo el espacio que ocupe el script de Juan!
Esto es inviable para scripts más grandes, y por eso nace “Pay To Script Hash”
Pay To Script Hash
Pay To Script Hash (P2SH) viene a simplificar el pago a scripts más complejos, como un multisig o cualquier otras condiciones de gasto. P2SH se podría resumir de la siguiente manera:
“Pagale al hash de un script. Cuando yo quiera gastarlo revelaré el script con el que se creó el hash, y además proveeré todos los datos necesarios para desbloquear el script”
Lo bueno es que ese script hash puede encodificarse como un address de la misma forma que lo hacíamos en P2PKH. La diferencia es que los addresses P2SH usan el prefijo “5”, lo que hace que estos addresses empiecen con “3”. Por ejemplo: 39RF6JqABiHdYHkfChV6USGMe6Nsr66Gzw
Volviendo al ejemplo de la multisig, ahora Juan no necesita enviarle el script completo a María, si no que sólo debe mandarle el hash del script. Maria puede pagar al script multisig creando el siguiente output:
OP_HASH160 <script_hash> OP_EQUAL
Al gastarlo, los nodos detectan ese patrón P2SH y activan una lógica especial, que consiste en primero ejecutar el script del output para validar que el hash del script coincida con el hash del output. Después ejecutan el script del input (en nuestro ejemplo el multisig)
Esto tiene varias ventajas:
- María no sabe qué tipo de script es ni debe preocuparse por eso
- María no debe pagar más fees cuando el script sea largo porque siempre le paga a un hash (20 bytes)
- Se reduce el tamaño del UTXO set en los nodos ya que no se guardan scripts
- Los addresses P2SH tienen chequeo de errores
Como consecuencia, se delega la responsabilidad de guardar el script al receptor, que tiene que presentarlo al momento de querer gastar esos BTC. Las fees por tamaño del script también caen sobre el receptor por el mismo motivo
Segregated Witness (SegWit)
En 2017 se activó Segwit, un soft fork que tenía como objetivo mejorar la escalabilidad de bitcoin y eliminar la maleabilidad de las transacciones, temas que no voy a desarrollar en este post. También dio por finalizada las discusiones de la comunidad por el tamaño del bloque.
Segwit cambió la estructura de las transacciones: las signatures, y demás datos necesarios para el desbloqueo, fueron sacados del scriptSig y movidos al área del witness, una nueva sección de la transacción que antes no existía
Pay To Witness Public Key Hash (P2WPKH)
Hablemos de “Pay To Witness Public Key Hash” (P2WPKH), el equivalente Segwit a P2PKH. Juan le envía a María su address Segwit, que es un «output segwit» encodificado en bech32. Luego María le envía 1 BTC a ese output, que se ve así:
OP_0 <juan_pubkey_hash>
Cuando Juan intente gastar ese BTC, los nodos Segwit detectarán que el script creado por María es P2WPKH y exigirán a Juan que ponga su signature y su pub key dentro del witness. Luego van a ejecutar el mismo set de commandos que se ejecuta con P2PKH.
Pay To Witness Script Hash (P2WSH)
También existe la versión Segwit de P2SH, que es P2WSH (“Pay To Witness Script Hash”).
Es muy similar a P2SH, pero ahora al gastar se debe presentar la(s) signature(s) y el script en el witness en lugar del scriptSig.
Un output P2WSH se ve así:
OP_0 <script_hash>
Entendiendo los outputs SegWit P2WPKH y P2WSH
Hay un patrón entre P2WPKH y P2WSH, y es que los outputs empiezan con el operador OP_0 seguido de un hash. Ese hash se lo conoce como “witness program” y puede representar una public key o un script. La diferencia es que el primero ocupa 20 bytes y el segundo ocupa 32 bytes.
Cuando se gasta un output Segwit, los nodos revisan si el witness program es de 20 o de 32 bytes. En caso de tener 20, activan la lógica que valida el pago a una pub key hash (P2WPKH). En caso de tener 32 bytes, activan la lógica que valida el pago a un script (P2WSH)
¿Por qué OP_0?
Porque se pretende que SegWit evolucione con el tiempo. La versión 0 se activó en 2017, pero en 2021 se activó la versión 1 de Segwit (Taproot) En resumen, los outputs Segwit se componen de:
<version> <witness_program>
Donde Version=0 significa Segwit, y Version=1 significa Taproot
Tanto Segwit v0 como v1 (Taproot) usan un nuevo formato de addresses, que resultan de la codificación bech32m del <version> seguido del <witness program>. Ambos tipos de addresses comienzan con el prefijo bc1:
- Segwit: bc1q… (q=0 en bech32)
- Taproot: bc1p… (p=1 en bech32)
Nested SegWit (P2SH-P2WPKH)
Antes de avanzar con Taproot, hablemos de Segwit anidado (P2SH-P2WPKH). Imaginemos que Juan quiere recibir un pago de María y quiere aprovechar los beneficios de Segwit, pero María todavía no tiene una Wallet compatible con Segwit.
La wallet de María no usa Segwit así que no sabe pagar a P2WPKH. Lo que puede hacerse es “encapsular” un output P2WPKH en un pago a un script (P2SH), cosa que la wallet de María seguramente conoce Juan envia un address P2SH y Maria le paga a ese script, usando el template P2SH:
OP_HASH160 <script_hash> OP_EQUAL
El output va a ser exactamente igual al de un P2SH. La particularidad es que el script de Juan (redeem script) es ni más ni menos que un output P2WPKH, osea:
OP_0 <juan_pub_key_hash>
Cuando Juan quiera gastar, los nodos primero detectarán que se está gastando un P2SH y entonces va a ejecutar la lógica especial de P2SH que: (1) chequea que el hash del script sea correcto, y luego (2) va a ejecutar el script deserializado. Lo interesante es que el script deserializado es el script de Juan:
OP_0 <pub_key_hash>
Un script Segwit!
Entonces los nodos Segwit van a buscar la signature y la public key al witness, como cualquier transacción Segwit P2WPKH. El resultado es que Juan pudo aprovechar parte de los beneficios de Segwit sin tener que esperar a que María se actualice a esa versión.
Los pagos P2SH-P2WPKH no tienen un nuevo formato de address porque a simple vista son un “Pay To Script Hash” (P2SH), y se codifican como tal (base58 con prefijo 5). Entonces las addresses de este tipo empiezan con 3 y son indistinguibles de, por ejemplo, una multisig pre-segwit
Taproot
En 2021 se activó Taproot (Segwit v1), un soft fork que trae cosas nuevas como las firmas Schnorr y las estructuras “MAST” (Merkelized Alternative Script Trees) que permiten usar scripts complejos de una forma más privada y eficiente que usando P2SH o P2WSH. Por ejemplo, los Silent Payments están construidos usando outputs de Taproot.
Supongamos que Juan quiere recibir un pago de María, pero quiere que los fondos puedan ser desbloqueados de 2 maneras: – Presentando su firma y la de su socio Pedro (multisig 2-2) – o con la firma de uno de los dos + la firma de su abogado si ya pasaron 90 días (multisig 2-3)
Esto ya podía hacerse en P2SH o P2WSH, usando el operador OP_IF para separar las distintas condiciones. Pero hay dos desventajas:
- Al gastar se debía presentar el script completo. Entonces todos verán las condiciones de gasto que existían y todas las pub keys involucradas
- Si las condiciones son muchas, el script completo va a ocupar mucho espacio. Entonces las fees al momento de gastar pueden ser muy altas
Estos problemas se resuelve con Taproot y MAST. ¿Cómo?
El MAST nos permite separar las condiciones de gastos y organizarlas como hojas de un árbol de hashes (un Merkle Tree). Con MAST podemos probar que un script pertenece a un árbol sin necesidad de revelar el árbol completo, porque esa es una propiedad que tienen los Merkle Trees.

Supongamos que María hace el pago y, unos días después, Juan y su socio deciden usar esos BTC para invertir en su negocio. En ese caso, Juan y Pedro pueden gastar revelando sus signatures y sólo la primer hoja del árbol (la musig 2-2) + un «índice» (una estructura de datos llamada control block)
De esa forma la fee será más barata, y además nadie sabrá que existía otra condición de gasto donde intervenía la public key de su abogado, porque ese otro script nunca se revela. Esto permite usar scripts complejos de forma barata y con mucha privacidad respecto a P2SH o P2WSH.
Voy a dejar los detalles para otro post, pero quiero aclarar que P2TR (“Pay to Taproot”) permite bloquear fondos en scripts complejos así como también en public keys, y en ambos a la vez!
Se podría decir que P2TR combina P2WPKH y P2WSH (pero mejor!) en un sólo output
Los outputs de Taproot comienzan con OP_1 seguido de un Witness program de 32 bytes (llamado Q) La codificación de estos outputs en bech32 da lugar a las addresses taproot: bc1p….
Resumen
Las formas de pago en Bitcoin han ido evolucionando con el paso del tiempo y en este artículo hicimos un repaso por los diferentes tipos de scripts y direcciones que existen: P2PK, P2PKH, P2SH, P2PKH, P2WSH.
Este post está basado en mi hilo de X:
Deja una respuesta