Explicación de cómo se ve una transacción OP_RETURN

¿Cómo se usa OP_RETURN y por qué se introdujo en primer lugar?

Respuestas (4)

Nota: Salí y aprendí cómo funciona el OP_RETURNcódigo de operación a nivel de byte en una transacción de bitcoin. Lo escribo aquí para que otros puedan aprender rápidamente. Primero, una breve historia de por qué estamos hablando de OP_RETURN.

En 2013, diferentes jugadores en el ecosistema de bitcoin intentaban incluir fragmentos de información en las transacciones para poder aprovechar la irreversibilidad de la cadena de bloques. Imagine, por ejemplo, que desea escribir un contrato y colocarlo en una ubicación inalterable que en cualquier fecha futura se pueda volver atrás para verificar que existió. Puedes hacer esto usando la cadena de bloques. Agrega algunos bits al valor scriptSig de la transacción que no alteran el resultado final de ejecutar ese script, pero le permiten almacenar información como "Por la presente declaro dar el activo A a la dirección XYZ en el momento UNIX_TIMESTAMP". Incluso había formas más extrañas en que las personas agregarían bits adicionales, como incluirlo en el valor BTC de una salida. A algunos miembros de la comunidad no les gustó esto, ya que vieron que estos bits adicionales contaminaban la cadena de bloques.

Para llegar a un término medio en estos puntos de vista opuestos, los desarrolladores centrales hicieron del código de operación OP_RETURN un código de operación válido para usar en una transacción de bitcoin, lo que permite usar 80 bytes arbitrarios en una transacción no gastable. Una buena explicación de esto se puede encontrar aquí:

https://bitcoinfoundation.org/bitcoin/core-development-update-5/

Posteriormente, en febrero de 2014, el recuento de bytes se redujo de 80 a 40 bytes. Este cambio está documentado en el siguiente enlace. Tenga en cuenta que en esta discusión de extracción aprendemos que no se puede incluir más de una salida con OP_RETURN en una sola transacción:

https://github.com/bitcoin/bitcoin/pull/3737

Ahora que tenemos el motivo detrás de OP_RETURN, veamos un ejemplo de OP_RETURN. Usé la API de chain.com para encontrar una transacción que tiene OP_RETURN en su scriptSig. El hash de ese tx es

8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684 

Asegúrese de estar conectado a un nodo bitcoind completamente cargado y ejecute este comando:

$> bitcoind getrawtransaction 8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684 1

que le dará esta salida:

{
"hex" : "0100000001c858ba5f607d762fe5be1dfe97ddc121827895c2562c4348d69d02b91dbb408e010000008b4830450220446df4e6b875af246800c8c976de7cd6d7d95016c4a8f7bcdbba81679cbda242022100c1ccfacfeb5e83087894aa8d9e37b11f5c054a75d030d5bfd94d17c5bc953d4a0141045901f6367ea950a5665335065342b952c5d5d60607b3cdc6c69a03df1a6b915aa02eb5e07095a2548a98dcdd84d875c6a3e130bafadfd45e694a3474e71405a4ffffffff020000000000000000156a13636861726c6579206c6f766573206865696469400d0300000000001976a914b8268ce4d481413c4e848ff353cd16104291c45b88ac00000000",
"txid" : "8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684",
"version" : 1,
"locktime" : 0,
"vin" : [
    {
        "txid" : "8e40bb1db9029dd648432c56c295788221c1dd97fe1dbee52f767d605fba58c8",
        "vout" : 1,
        "scriptSig" : {
            "asm" : "30450220446df4e6b875af246800c8c976de7cd6d7d95016c4a8f7bcdbba81679cbda242022100c1ccfacfeb5e83087894aa8d9e37b11f5c054a75d030d5bfd94d17c5bc953d4a01 045901f6367ea950a5665335065342b952c5d5d60607b3cdc6c69a03df1a6b915aa02eb5e07095a2548a98dcdd84d875c6a3e130bafadfd45e694a3474e71405a4",
            "hex" : "4830450220446df4e6b875af246800c8c976de7cd6d7d95016c4a8f7bcdbba81679cbda242022100c1ccfacfeb5e83087894aa8d9e37b11f5c054a75d030d5bfd94d17c5bc953d4a0141045901f6367ea950a5665335065342b952c5d5d60607b3cdc6c69a03df1a6b915aa02eb5e07095a2548a98dcdd84d875c6a3e130bafadfd45e694a3474e71405a4"
        },
        "sequence" : 4294967295
    }
],
"vout" : [
    {
        "value" : 0.00000000,
        "n" : 0,
        "scriptPubKey" : {
            "asm" : "OP_RETURN 636861726c6579206c6f766573206865696469",
            "hex" : "6a13636861726c6579206c6f766573206865696469",
            "type" : "nulldata"
        }
    },
    {
        "value" : 0.00200000,
        "n" : 1,
        "scriptPubKey" : {
            "asm" : "OP_DUP OP_HASH160 b8268ce4d481413c4e848ff353cd16104291c45b OP_EQUALVERIFY OP_CHECKSIG",
            "hex" : "76a914b8268ce4d481413c4e848ff353cd16104291c45b88ac",
            "reqSigs" : 1,
            "type" : "pubkeyhash",
            "addresses" : [
                "1HnhWpkMHMjgt167kvgcPyurMmsCQ2WPgg"
            ]
        }
    }
],
"blockhash" : "000000000000000004c31376d7619bf0f0d65af6fb028d3b4a410ea39d22554c",
"confirmations" : 2655,
"time" : 1404107109,
"blocktime" : 1404107109
}

Ahora, mire la lista de salidas de esta transacción, en particular la primera. Al hacer referencia a la página de Bitcoin Wiki en Script , el lenguaje de programación basado en pila de Bitcoin, podemos ver aquí que el OP_RETURNcódigo de operación está representado por el valor hexadecimal 0x6a. Este primer byte es seguido por un byte que representa la longitud del resto de bytes en scriptPubKey. En este caso vemos el valor hexadecimal Ox13, lo que significa que hay 19 bytes más. Estos bytes comprenden los menos de 40 bytes arbitrarios que puede enviar en una transacción marcada por el OP_RETURNcódigo de operación. Si mete los bytes del mensaje en un decodificador UTF8, verá que

636861726c6579206c6f766573206865696469

se convierte en "charley ama a heidi". ¡Ay! Es casi como una versión digital de la talla del árbol del corazón romántico de una pareja. Ahora entiendes a nivel de byte cómo OP_RETURNse supone que funciona. Ahora puede escribir software que busque el OP_RETURNcódigo de operación en el scriptPubKey de una salida y usarlo para verificar un contrato o algún otro activo digital.

Un aspecto importante de OP_RETURN es que las salidas que lo usan de la manera estándar se pueden probar como no gastables. Esto significa que los nodos pueden eliminar inmediatamente dichas salidas de su caché de salidas no gastadas y potencialmente olvidarse de ellas por completo (aunque Bitcoin Core aún no lo hace). Esto hace que las transacciones OP_RETURN sean mucho menos costosas para la red que otras formas de introducir datos en la cadena de bloques.
Para su información, si alguien está buscando decodificar ese mensaje 636861726c6579206c6f766573206865696469en php, es el valor hexadecimal, así que usehex2bin()
¿Por qué esto le cuesta menos a la red que simplemente enviar 1 satoshi a una dirección arbitraria que contiene los 20 bytes de información en sí?
@NathanParker Porque con OP_RETURN, el nodo sabe que el índice de salida de la transacción no se puede gastar y simplemente puede ignorarlo. Mientras que al enviar 1 satoshi, el nodo deberá mantener esa salida no gastada en la memoria o en una base de datos, esperando hasta que alguien la gaste algún día.
@almel Hoy en día, el comando para obtener los detalles de tx es bitcoin-cliy no bitcoind.
En *NIX xxdse puede usar el comando. echo 636861726c6579206c6f766573206865696469 | xxd -p -rdevolucionescharley loves heidi
¿Cómo es posible que esta famosa transacción contenga más de 80 bytes?
(empuja 983 bytes)
Usted dice que "no se puede incluir más de una salida con OP_RETURN en una sola transacción" y proporciona una solicitud de extracción como fuente para esto. ¿En qué parte de esta discusión de solicitud de extracción se menciona esto?
Para aquellos que deseen decodificar el mensaje usando JavaScript, el one-liner en Node seríaBuffer.from('636861726c6579206c6f766573206865696469', 'hex').toString('utf8');
Según el wiki de Script : it is usually considered non-standard (though valid) for a transaction to have more than one OP_RETURN output or an OP_RETURN output with more than one pushdata op.
¿Por qué los bytes que quiero guardar en la cadena de bloques tienen que venir después de OP_RETURN y no antes?
@theymos Entonces, ¿es solo una convención/consenso que hace que estas transacciones quemen las monedas, o hay otras razones técnicas?
@theymos twitter.com/lopp/status/947507679936774145?lang=en Aquí dicen que las monedas no se queman.
¿Puedo incluir una addressesentrada scriptPubKeypara indicar el destinatario del mensaje?

Si desea escribir OP_RETURNs en la cadena de bloques sin entrar en los aspectos internos de cómo se construyen las transacciones, una manera fácil es usar nuestras bibliotecas para PHP y Python:

https://github.com/coinspark/php-OP_RETURN

https://github.com/coinspark/python-OP_RETURN

Estos admiten el envío de transacciones individuales con un OP_RETURN adjunto o el envío de un lote de transacciones vinculadas para incrustar piezas de contenido más grandes. Ese contenido se puede recuperar de la cadena de bloques utilizando un único identificador.

Suponiendo que está utilizando Bitcoin Core 0.11, puede cambiar el valor de OP_RETURN_MAX_BYTESa 80, en lugar de 40como está actualmente en el código.

OP_RETURNes una forma de obtener datos arbitrarios en la cadena de bloques con menos carga para la red

Como consecuencia, los datos también estarán presentes en menos clientes, ya que OP_RETURNlos datos pueden eliminarse.

El objetivo de esta respuesta es explicar lo que explicó https://bitcoin.stackexchange.com/a/29555/21282 pero con un poco más de contexto para los novatos de Bitcoin.

Cómo se ve una transacción estándar

Como se ve en el desensamblado de JSON de https://bitcoin.stackexchange.com/a/29555/21282 , cada transacción tiene una lista de salidas y cada salida tiene un script.

El script más común, con diferencia, es pay-to-pubkey-hash, que básicamente dice:

esta salida puede ser consumida por la persona que controla la clave privada de esta clave pública

o en términos más simples "pagar X bitcoint a la dirección Y".

Ese script tiene formato:

OP_DUP OP_HASH160 <length-of-hash> <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

donde pubKeyHash es de 20 bytes y los otros 5 campos son de 1 byte.

Es imposible saber si un hash de transacción estándar es un hash real o datos arbitrarios

Debido a que pubKeyHashes un hash, es imposible saber si ese es el hash real de algo o datos arbitrarios que alguien quiere codificar en la cadena de bloques.

El problema es: si agrega datos arbitrarios allí, no tendrá una clave privada correspondiente para reclamar esos fondos. Entonces, lo que hace la gente es hacer transacciones con la menor cantidad posible que los mineros estén dispuestos a tomar para el trabajo de verificación.

Ahora, cada transacción en la cadena de bloques toma como entrada una salida anterior no gastada.

Por lo tanto, incrustar estos datos le cuesta un poco, porque esa salida no se puede gastar: nunca se puede usar como entrada de otra transacción.

Para verificar si una transacción es válida, las implementaciones de Bitcoin deben mantener una lista completa de cada salida no gastada jamás creada, conocida como el conjunto UTXO .

Las salidas gastadas se pueden recortar para ahorrar espacio, pero las no gastadas no.

Por lo tanto, cada vez que graba su salida de hash de clave pública falsa, obliga a cada implementación a mantener esa información para siempre, ya que esos fondos nunca se pueden gastar.

Como OP_RETURNresuelve ese problema

OP return es otro tipo de transacción de secuencia de comandos diferente de la transacción estándar de pago a hash de clave pública.

Como se menciona en: https://en.bitcoin.it/wiki/Script#Provably_Unspendable.2FPrunable_Outputs , la transacción tiene simplemente la forma:

OP_RETURN <data>

OP_RETURNsimplemente detiene la ejecución del script con una falla, lo que hace imposible que alguien use esa salida como entrada de otra transacción.

Por lo tanto, cuando una implementación de bitcoin ve esa transacción, puede decidir de inmediato que no se puede gastar, a diferencia de la transacción pay-to-pubkey-hash anterior, donde es imposible tomar esa decisión. Es por eso que esta transacción se llama "probablemente indiscutible".

Entonces, el minero puede extraer si paga una tarifa de minería, pero luego las implementaciones lo eliminan inmediatamente del conjunto UTXO.

Esto permite que el conjunto de UTXO sea más pequeño, lo que hace que Bitcoin sea más eficiente para todos.

Pero por otro lado, también significa que sus datos incrustados estarán presentes en las computadoras de menos personas.

Si "agrego datos arbitrarios", ¿no invalidará la transacción y no se aceptará en la cadena de bloques? ¿O es solo la dirección del destinatario y en lugar de poner mi propia dirección, solo pongo algunos datos arbitrarios?
@RonyTesler, simplemente coloca datos arbitrarios en lugar de una dirección real que controla. Pero dado que las direcciones parecen de naturaleza completamente aleatoria (son claves públicas), es imposible que los pares las distingan, por lo que deben agregarse a la cadena. Y debido a que no tiene la clave privada, es imposible para usted (o cualquier otra persona) reclamar fondos más adelante.

En caso de que esté aquí tratando de convertir OP_RETURN en valores legibles:

Nota: Esto es javascript/mecanografiado

export default class OpReturnConverter {

    // Input -> <Buffer 35 33 36 39...>
    // Output -> 53696d706c6520616e737765722120f09f988a
    public static convertBufferToHex(buffer: Buffer) {
        const str = buffer.toString('hex')
        return Buffer.from(str, 'hex').toString()
    }

    // Input -> 53696d706c6520616e737765722120f09f988a
    // Output -> Simple answer! 😊
    public static convertHexToString(hex: string) {
        return Buffer.from(hex, 'hex').toString()
    }

    // Input -> Simple answer! 😊
    // Output -> <Buffer 35 33 36 39...>
    public static convertStringToBuffer(message: string) {
        const hexBuffer = Buffer.from(message).toString('hex')
        return Buffer.from(hexBuffer)
    }

}

Resultados

const string = 'Simple answer! 😊'
console.log('Original ->', string)

const buf = OpReturnConverter.convertStringToBuffer(string)
console.log('Buffer ->', buf)

const hex = OpReturnConverter.convertBufferToHex(buf)
console.log('Hex ->', hex)

const unhex = OpReturnConverter.convertHexToString(hex)
console.log('Unhex ->', unhex)