Mastering Bitcoin
7. Transacciones » Transacciones Estándar » Pago-a-Hash-de-Script (P2SH)
Página 47 de 98
Transacciones Estándar
En los años iniciales del desarrollo de bitcoin, los desarrolladores introdujeron algunas limitaciones en los tipos de scripts que podían ser procesados por el cliente de referencia. Estas limitaciones se encuentran codificadas en una función llamada isStandard() (es estándar), la cual define cinco tipos de transacciones «estándar». Estas limitaciones son temporales y pueden encontrarse removidas para cuando leas esto. Hasta entonces, los cinco tipos de scripts de transacciones son los únicos aceptados por el cliente de referencia y la mayoría de los mineros que ejecutan el cliente de referencia. Aunque es posible crear transacciones no estándar que contengan un script que no es uno de los tipos estándar, debes encontrar un minero que no aplique estas limitaciones para minar esa transacción en un bloque.
Compruebe el código fuente del cliente Bitcoin Core (la implementación de referencia) para ver qué está permitido actualmente como script de transacción válido.
Los cinco tipos estándar de scripts de transacción son pago-a-hash-de-clave-pública (pay-to-public-key-hash, o P2PKH), clave-pública (public-key), multifirma (multi-signature, limitado a 15 claves), pago-a-hash-de-script (pay-to-script-hash, o P2SH), y salida de datos (OP_RETURN), los cuales se describen en más detalle en las secciones siguientes.
Pago-a-Hash-de-Clave-Pública (P2PKH)
La vasta mayoría de las transacciones procesadas en la red bitcoin son transacciones P2PKH. Estas contienen un script de bloqueo que solicita a la salida un hash de clave pública, más comúnmente conocido como una dirección bitcoin. Las transacciones que pagan a una dirección bitcoin contienen scripts P2PKH. Una salida bloqueada por un script P2PKH puede ser desbloqueada (gastada) presentando una clave pública y una firma digital creada por la clave privada correspondiente.
Por ejemplo, veamos el pago de Alice al Café de Bob nuevamente. Alice hizo un pago de 0,015 bitcoins a la dirección bitcoin del café. Esa salida de transacción tendría un script de bloqueo del tipo:
OP_DUP OP_HASH160 <Hash de Clave Pública del Café> OP_EQUAL OP_CHECKSIG
El Hash de Clave Pública del Café es equivalente a la dirección bitcoin del café, sin la codificación Base58Check. La mayoría de las aplicaciones mostrarían el hash de clave pública en codificación hexadecimal y no el familiar formato Base58Check de la dirección bitcoin comenzado en «1».
El script de bloqueo anterior puede ser satisfecho con un script de desbloqueo de la forma:
<Firma del Café> <Clave Pública del Café>
Los dos scripts juntos formarían el siguiente script de validación combinado:
<Firma del Café> <Clave Pública del Café> OP_DUP OP_HASH160
<Hash de Clave Pública del Café> OP_EQUAL OP_CHECKSIG
Cuando es ejecutado, este script combinado será evaluado a VERDADERO si, y solo si, el script de desbloqueo cumple las condiciones establecidas por el script de bloqueo. En otras palabras, el resultado será VERDADERO si el script de desbloqueo contiene una firma válida proveniente de la clave privada del café que corresponde al hash de clave pública establecido como obstrucción.
Las figuras siguientes muestran (en dos partes) una ejecución paso a paso del script combinado, el cual demostrará que es una transacción válida.

Figura 3. Evaluando un script para una transacción P2PKH (Parte 1 de 2)
Pago-a-Clave-Pública
pago-a-hash-de-clave-pública (pay-to-public-key) es una forma más simple de un pago bitcoin que pago-a-hash-de-clave-pública. Con esta forma de script la clave pública misma es almacenada en el script de bloqueo, en vez de un hash de clave pública como se vio en P2PKH anteriormente, lo cual resulta mucho más corto. El pago-a-hash-de-clave-pública fue inventado por Satoshi para hacer las direcciones de bitcoin más cortas, para facilidad de uso. Hoy en día el pago-a-clave-pública se ve principalmente en transacciones coinbase, generadas por software de minería más antiguo que no ha sido actualizado para utilizar P2PKH.
Un script de bloqueo de pago-a-clave-pública se ve así:
<Clave Pública A> OP_CHECKSIG
El script de desbloqueo correspondiente que debe presentarse para desbloquear este tipo de salida es una simple firma, como esta:
<Firma de Clave Pública A>
El script combinado, el cual es validado por el software de validación de transacción, es:
<Firma de Clave Pública A> <Clave Pública A> OP_CHECKSIG
El script es una simple invocación del operador CHECKSIG, el cual valida que la firma pertenezca a la clave correcta y devuelve VERDADERO en la pila.

Figura 4. Evaluando un script para una transacción P2PKH (Parte 2 de 2)
Multi-Firma
Los scripts multifirma establecen una condición donde N claves públicas son registradas en el script y al menos M de esas deben proveer firmas para liberar la obstrucción. Esto se conoce también como un esquema M-de-N, donde N es el número total de claves y M es el umbral de firmas requeridas para la validación. Por ejemplo, una multifirma 2-de-3 es una donde tres claves públicas son listadas como potenciales firmantes y al menos dos de ellas deben ser usadas para crear firmas para una transacción válida para gastar los fondos. En este momento los scripts multifirma se encuentran limitados a como máximo a 15 claves públicas listadas, lo cual significa que es posible hacer cualquier combinación multifirma desde 1-de-1 hasta 15-de-15. La limitación de 15 claves listadas puede haber cambiado a fecha en que este libro sea publicado, así que examine la función isStandard() para ver qué es aceptado actualmente por la red.
La forma general de un script de bloqueo estableciendo una condición multifirma M-de-N es:
M <Clave Pública 1> <Clave Pública 2> … <Clave Pública N> N OP_CHECKMULTISIG
Donde N es el número total de claves públicas listadas y M es el umbral de firmas requeridas para gastar la salida.
Un script de bloqueo estableciendo una condición multifirma 2-de-3 se ve así:
2 <Clave Pública A> <Clave Pública B> <Clave Pública C> 3 OP_CHECKMULTISIG
El script de bloqueo anterior puede ser satisfecho con un script de desbloqueo conteniendo pares de firmas y claves públicas:
OP_0 <Firma B> <Firma C>
O cualquier combinación de dos firmas a partir de las claves privadas correspondientes a las tres claves públicas listadas.
El prefijo OP_0 es requerido por un error en la implementación original de CHECKMULTISIG por el cual se saca un item de más de la pila. Es ignorado por CHECKMULTISIG y es sencillamente un marcador de posición.
Los dos scripts juntos formarían el script de validación combinado:
OP_0 <Firma B> <Firma C> 2 <Clave Pública A> <Clave Pública B> <Clave Pública C> 3 OP_CHECKMULTISIG
Cuando es ejecutado, el script combinado evaluará a VERDADERO si, y solo si, el script de desbloqueo cumple las condiciones establecidas por el script de bloqueo. En este caso, la condición es si el script de desbloqueo contiene una firma válida proveniente de las dos claves privadas que corresponden a dos de las tres claves públicas establecidas como obstrucciones.
Salida de Datos (OP_RETURN)
El libro contable bitcoin distribuido y con sellado de tiempo, la cadena de bloques, tiene muchos potenciales usos más allá de pagos. Varios desarrolladores han intentado usar el lenguaje de scripting de transacciones para tomar ventaja de la seguridad y resistencia del sistema para aplicaciones como servicios de notaría digital, contratos inteligentes y certificado de acciones. Los primeros intentos de usar el lenguaje de script de bitcoin para estos propósitos involucraron crear salidas de transacciones que registraran datos en la cadena de bloques; por ejemplo, para registrar una huella digital de un archivo de forma que cualquiera pudiera establecer prueba de existencia de ese archivo en una fecha específica por referencia a dicha transacción.
El uso de la cadena de bloques de bitcoin para almacenar información sin relación a pagos bitcoin es un tema controvertido. Muchos desarrolladores lo consideran un abuso y prefieren desalentarlo. Otros lo ven como una demostración de las poderosas posibilidades de la tecnología de la cadena de bloques y prefieren alentar su experimentación. Quienes objetan a la inclusión de datos no relacionados a pagos argumentan que causa «hinchazón de la cadena de bloques», colocando una carga sobre quienes corren nodos bitcoin completos al tener que almacenar datos que la cadena de bloques no fue pensada para albergar. Adicionalmente, esas transacciones crean UTXOs que no pueden ser gastados, utilizando la dirección bitcoin de destino como un campo libre de 20 bytes. Ya que la dirección es utilizada para datos no corresponde a una clave privada y la UTXO resultante no puede ser gastada jamás; es un falso pago. Estas transacciones que no pueden ser gastadas no pueden ser removidas de la colección de UTXOs y provocan que el tamaño de la base de datos de UTXOs crezca o «se hinche» para siempre.
En la versión 0.9 del cliente Bitcoin Core se alcanzó un mutuo acuerdo con la introducción del operador OP_RETURN. OP_RETURN permite a los desarrolladores añadir 80 bytes de datos no relacionados a pagos a la salida de una transacción. Sin embargo, a diferencia del uso de UTXOs falsas, el operador OP_RETURN crea una salida demostrablemente no gastable explícitamente, la cual no necesita ser almacenada en la colección de UTXOs. Salidas del tipo OP_RETURN son registradas en la cadena de bloques, por lo que consumen espacio en disco y contribuyen al incremento de tamaño de la cadena de bloques, pero no son almacenadas en la colección de UTXOs y por ende no hinchan la reserva de memoria de UTXOs ni incomodan a los nodos completos con el costo de memoria RAM adicional.
Los scripts de OP_RETURN se ven así:
OP_RETURN <datos>
La porción de datos se limita a 80 bytes y frecuentemente representa un hash, tal como la salida del algoritmo SHA256 (32 bytes). Muchas aplicaciones colocan un prefijo en frente de los datos para a yudar a identificar la aplicación. Por ejemplo, el servicio de autorización bajo notario digital Proof of Existence usa el prefijo de 8 bytes «DOCPROOF» el cual es ASCII codificado como 44f4350524f4f46 en hexadecimal.
Tenga en cuenta que no existe un «script de desbloqueo» que corresponda a un OP_RETURN que pudiera ser usado para «gastar» una salida OP_RETURN. El propósito de OP_RETURN es que no se pueda gastar el dinero bloqueado en esa salida y por lo tanto no requiere ser conservado en la colección UTXO como potencialmente gastable. OP_RETURN es demostrablemente no gastable.
OP_RETURN es generalmente una salida con un monto de cero bitcoins, ya que cualquier monto en bitcoins asignado a tal salida sería efectivamente perdido para siempre. Si un OP_RETURN es encontrado por el software de validación de scripts, resultaría en la detención inmediata de la ejecución del script de validación y marca de la transacción como inválida. Por este motivo, si accidentalmente se referencia una salida OP_RETURN como entrada de una transacción, esa transacción será inválida.
Una transacción estándar (una que cumple con los chequeos de isStandard()) puede tener tan solo una salida OP_RETURN. Sin embargo, una salida OP_RETURN única puede ser combinada en una transacción con varias salidas de otros tipos.
Dos nuevas opciones de línea de comandos han sido añadidas en Bitcoin Core en su versión 0.10. La opción datacarrier controla la transmisión y minado de transacciones OP_RETURN, con el valor por defecto de «1» para permitirlas. La opción datacarriersize toma un argumento numérico especificando el tamaño máximo en bytes de los datos en OP_RETURN, con 40 bytes por defecto.
OP_RETURN fue propuesto inicialmente con un límite de 80 bytes, pero el límite fue reducido a 40 bytes cuando la funcionalidad fue liberada. En febrero de 2015, en la versión 0.10 de Bitcoin Core, el límite fue elevado nuevamente a 80 bytes. Los nodos pueden optar por no transmitir o minar OP_RETURNs, o simplemente transmitir y minar OP_RETURNs que contengan menos de 80 bytes de datos.
Pago-a-Hash-de-Script (P2SH)
El pago-a-hash-de-script (P2SH) fue introducido en 2012 como un poderoso nuevo tipo de transacción que generalmente simplifica el uso de scripts de transacciones complejos. Para explicar la necesidad de P2SH, veamos un ejemplo práctico.
En el capítulo 3 presentamos a Mohammed, un importador de productos electrónicos en Dubai. La compañía de Mohammed usa la funcionalidad multifirma de bitcoin de forma exclusiva para sus cuentas corporativas. Los scripts multifirma son uno de los usos más comunes de las capacidades avanzadas de scripting de bitcoin y son una funcionalidad muy potente. La compañía de Mohammed usa un script multifirma para todos los pagos de clientes, conocidos en contabilidad como «cuentas por cobrar». Con el esquema multifirma, cualquier pago hecho por clientes es bloqueado de forma que requieran al menos dos firmas para ser liberados, una de Mohammed y otra de sus socios o un abogado con una clave de backup. Un esquema multifirma como ese ofrece a la gerencia corporativa controles y la protege de robo, malversación o pérdida.
El script resultante es bastante largo y se ve así:
2 <Clave Pública de Mohammed> <Clave Pública de Socio1> <Clave Pública de Socio2> <Clave Pública de Socio3> <Clave Pública de Abogado> 5 OP_CHECKMULTISIG
Aunque los scripts multifirma son una funcionalidad potente, son algo engorrosos de usar. Dado el script anterior, Mohammed tendría que comunicar este script a cada comprador antes de realizarse el pago. Cada cliente tendría que usar un software de cartera bitcoin especial con la habilidad de crear scripts de transacción personalizados, y cada cliente tendría que entender cómo crear una transacción utilizando scripts personalizados. Es más, la transacción resultante tendría que ser alrededor de cinco veces mayor que una transacción de pago común y corriente, ya que este script contiene claves públicas muy largas. La carga de esa transacción extra larga recaería sobre el cliente en forma de tarifas. Por último, un script de transacción grande como este terminaría en la colección de UTXOs en la RAM de cada nodo completo hasta ser gastado. Todos estos problemas hacen el uso de scripts de salida complejos difícil en la práctica.
Pago-a-Hash-de-Script (pay-to-script-hash, o P2SH) fue desarrollado para resolver estas dificultades prácticas y hacer el uso de scripts complejos tan fácil como un pago a una dirección bitcoin. Con pagos P2SH los scripts de bloqueo complejos son reemplazados con su huella digital, un hash criptográfico.
Cuando una transacción que intenta gastar una UTXO es luego presentada, debe contener el script que concuerda con el hash, además del script de desbloqueo. En términos simples, P2SH significa «pagar a un script que concuerde con este hash, un script que será presentado más tarde cuando esta salida sea gastada».
En las transacciones P2SH, el script de bloqueo que es reemplazado por un hash es referenciado como el script de liquidación (redeem script), ya que es presentado al sistema al momento de liquidación en vez de como un script de bloqueo. Script complejo sin P2SH muestra el script sin P2SH y Script complejo como P2SH muestra el mismo script codificado con P2SH.
Tabla 4. Script complejo sin P2SH

Tabla 5. Script complejo como P2SH

Como puede ver de las tablas, con P2SH el script complejo que detalla las condiciones para gastar la salida (script de liquidación) no es presentado en el script de bloqueo. En cambio, solo su hash se encuentra en el script de bloqueo y el script de liquidación en sí es presentado luego, como parte del script de desbloqueo cuando la salida es gastada. Esto mueve la carga tarifaria y la complejidad del remitente al destinatario (gastador) de la transacción.
Observemos la compañía de Mohammed, el complejo script multifirma, y los scripts P2SH resultantes.
Primero, el script multifirma que usa la compañía de Mohammed para todos sus pagos de clientes entrantes:
2 <Clave Pública de Mohammed> <Clave Pública de Socio1> <Clave Pública de Socio2> <Clave Pública de Socio3> <Clave Pública de Abogado> 5 OP_CHECKMULTISIG
Si los marcadores de posición son reemplazados por claves públicas reales (mostradas aquí como números de 520 bits comenzados en 04) se puede observar que el script se vuelve muy largo:
04C16B8698A9ABF84250A7C3EA7EEDEF9897D1C8C6ADF47F06CF73370D74DCCA01CDCA79DCC5C395D7EEC6984
D83F1F50C900A24DD47F569FD4193AF5DE762C58704A2192968D8655D6A935BEAF2CA23E3FB87A3495E7AF308
EDF08DAC3C1FCBFC2C75B4B0F4D0B1B70CD2423657738C0C2B1D5CE65C97D78D0E34224858008E8B49047E632
48B75DB7379BE9CDA8CE5751D16485F431E46117B9D0C1837C9D5737812F393DA7D4420D7E1A9162F0279CFC1
0F1E8E8F3020DECDBC3C0DD389D99779650421D65CBD7149B255382ED7F78E946580657EE6FDA162A187543A9
D85BAAA93A4AB3A8F044DADA618D087227440645ABE8A35DA8C5B73997AD343BE5C2AFD94A5043752580AFA1E
CED3C68D446BCAB69AC0BA7DF50D56231BE0AABF1FDEEC78A6A45E394BA29A1EDF518C022DD618DA774D207D1
37AAB59E0B000EB7ED238F4D800 5 OP_CHECKMULTISIG
La totalidad de este script puede ser en cambio reemplazado por un hash criptográfico de 20 bytes, aplicando primero el algoritmo de hashing SHA256 y luego el algoritmo RIPEMD160 sobre el resultado.
El hash de 20 bytes del script anterior es:
54c557e07dde5bb6cb791c7a540e0a4796f5e97e
Una transacción P2SH bloquea la salida a este hash en vez del script más largo, usando el script de bloqueo:
OP_HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e OP_EQUAL
El cual, como se puede ver, es mucho más breve. En vez de «pagar a este script multifirma de 5 claves», la transacción P2SH equivalente es «pagar al script con este hash». Un cliente realizando un pago a la compañía de Mohammed solo necesita incluir este script de bloqueo mucho más corto en su pago.
Cuando Mohammed desea gastar esta UTXO, debe presentar el script de liquidación original (cuyo hash bloqueó la UTXO) y las firmas necesarias para desbloquearla, así:
<Firma1> <Firma2> <2 CP1 CP2 CP3 CP4 CP5 5 OP_CHECKMULTISIG>
Ambos scripts son combinados en dos etapas. Primero, el script de liquidación es chequeado contra el script de bloqueo para asegurar que el hash concuerda:
<2 CP1 CP2 CP3 CP4 CP5 5 OP_CHECKMULTISIG> OP_HASH160 <hash de script de liquidación> OP_EQUAL
Si el hash del scritp de liquidación concuerda, el script de desbloqueo es ejecutado por su cuenta para desbloquear el script de liquidación:
<Firma1> <Firma2> 2 CP1 CP2 CP3 CP4 CP5 5 OP_CHECKMULTISIG
Direcciones pago-a-hash-de-script
Otra parte importante de la funcionalidad de P2SH es la habilidad de codificar un hash de un script en una dirección, tal como se define en BIP0013. Las direcciones P2SH son codificaciones Base58Check del hash de 20 bytes de un script, tal como las direcciones bitcoin son codificaciones Base58Check del hash de una clave pública de 20 bytes. Las direcciones P2SH usan el prefijo de versión «5», que resulta en direcciones codificadas en Base58Check comenzadas en «3». Por ejemplo, el script complejo de Mohammed, hasheado y codificado en Base58Check como una dirección P2SH se convierte en 39RF6JqABiHdYHkfChV6USGMe6Nsr66Gzw. Ahora Mohammed puede distribuir esta «dirección» a sus clientes y ellos pueden usar prácticamente cualquier cartera bitcoin para hacer un pago sencillo, como si fuera una dirección bitcoin. El prefijo 3 da un indicio de que este es un tipo especial de dirección, uno que corresponde a un script en vez de a una clave pública, pero funciona exactamente de la misma manera que un pago a una dirección bitcoin salvando esa diferencia.
Las direcciones P2SH esconden toda la complejidad de forma que la persona realizando el pago no vea el script.
Beneficios del pago-a-hash-de-script
La funcionalidad de pago-a-hash-de-script ofrece los siguientes beneficios comparado al uso directo de scripts complejos en bloqueo de salidas:
Scripts complejos son reemplazados por huellas más cortas en la salida de transacción, reduciendo la transacción.
Los scripts pueden ser codificados como una dirección, de forma que el remitente y la cartera del remitente no necesitan ingeniería compleja para implementar P2SH.
P2SH desplaza la carga de construir el script al destinatario, no el remitente.
P2SH mueve la carga en almacenamiento de datos para scripts largos de la salida (la cual se encuentra en la colección de UTXOs) a la entrada (almacenada en la cadena de bloques).
P2SH mueve la carga en almacenamiento de datos para el script largo del tiempo presente (pago) a un tiempo futuro (cuando es gastado).
P2SH mueve los costos de tarifas de transacción de un script largo del remitente al destinatario, quien debe incluir el largo script de liquidación para gastarlo.
Script de liquidación y validación isStandard
Antes de la versión 0.9.2 del cliente Bitcoin Core, el pago-a-hash-de-script se encontraba limitado a tipos de scripts de transacciones bitcoin estándar, validados por la función isStandard(). Eso significa que el script de liquidación presentado en la transacción de gasto podía ser tan solo uno de los tipos estándar: P2PK, P2PKH, o multifirma, excluyendo OP_RETURN y P2SH mismo.
Hacia la versión 0.9.2 del cliente Bitcoin Core, las transacciones P2SH pueden contener cualquier script válido, haciendo al estándar P2SH mucho más flexible y permitiendo experimentación con muchos tipos de transacciones novedosos y complejos.
Nótese que no es posible poner un P2SH dentro de un script de liquidación P2SH ya que la especificación P2SH no es recursiva. Tampoco es posible utilizar OP_RETURN dentro de un script de liquidación ya que OP_RETURN no puede ser liquidado por definición.
Nótese que como el script de liquidación no se presenta a la red hasta el momento de gastar una salida P2SH, si usted bloquea una salida con el hash de una transacción inválida será procesado de todos modos. Sin embargo, no podrá gastarlo ya que la transacción de gasto, la cual incluye el script de liquidación, no será aceptado ya que es un script inválido. Esto crea un riesgo, ya que es posible bloquear bitcoins en un P2SH que no puede ser gastado. La red aceptará la obstrucción P2SH aun si corresponde a un script de liquidación inválido, ya que el hash del script no da ninguna indicación de qué script representa.
Los scripts de bloqueo P2SH contienen el hash de un script de liquidación, el cual no da pistas acerca del contenido del script de liquidación mismo. La transacción P2SH será considerada válida y aceptada aun si el script de liquidación no lo es. Es posible bloquear bitcoins accidentalmente de forma que no puedan ser gastados luego.