¿Cómo se usa OP_RETURN y por qué se introdujo en primer lugar?
Nota: Salí y aprendí cómo funciona el OP_RETURN
có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_RETURN
có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_RETURN
có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_RETURN
se supone que funciona. Ahora puede escribir software que busque el OP_RETURN
código de operación en el scriptPubKey de una salida y usarlo para verificar un contrato o algún otro activo digital.
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_BYTES
a 80
, en lugar de 40
como está actualmente en el código.
OP_RETURN
es 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_RETURN
los 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 pubKeyHash
es 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_RETURN
resuelve 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_RETURN
simplemente 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.
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)
ellos
Diseños OAC
636861726c6579206c6f766573206865696469
en php, es el valor hexadecimal, así que usehex2bin()
nathan parker
Nayuki
Thalis K.
bitcoin-cli
y nobitcoind
.usuario207863
xxd
se puede usar el comando.echo 636861726c6579206c6f766573206865696469 | xxd -p -r
devolucionescharley loves heidi
robermann
robermann
dionisio
Thalis K.
Buffer.from('636861726c6579206c6f766573206865696469', 'hex').toString('utf8');
Thalis K.
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
.Rony Tesler
Rony Tesler
Rony Tesler
Guillermo Entriken
addresses
entradascriptPubKey
para indicar el destinatario del mensaje?