En esta publicación se utilizará Bitcoin Core para explorar las limitaciones y las mejores prácticas al incorporar datos en las transacciones de la blockchain.

Los propósitos puntuales de esta sección son:

  • Reconocer la estructura de los datos de bloques y de transacciones.
  • Reconocer el propósito de los códigos de operación de Bitcoin Script que se usan comúnmente en las partes de entrada y salida de un proceso de transacción.
  • Explorar las limitaciones y las mejores prácticas para incorporar datos en transacciones de blockchain.

¡Usar estas habilidades le ayudará a construir los componentes de su propia cadena de bloques simple y privada desde cero!

Modelos de datos en Blockchain

Para entender cómo se almacena la información en cualquier blockchain, es necesario aclarar los modelos de datos del bloque y de la transacción. Anteriormente se mencionó que el modelo de datos de un bloque se compone de dos partes: Un encabezado y un cuerpo.

El encabezado de bloque almacena la siguiente información:

  • Hash del bloque anterior: el valor hash del bloque inmediatamente anterior a un bloque determinado en la cadena. Esto es lo que une los bloques en la blockchain.
  • Hora: la hora en que se creó el bloque también se mantiene en el encabezado.
  • Raíz de Merkle: la raíz de Merkle es un hash que representa todas las transacciones incluidas en el bloque. Para obtener la raíz de Merkle, los pares de transacciones dentro de un bloque se combinan repetidamente. Cada par da como resultado un único hash. Luego, el hash de dos pares de transacciones se vuelve a mezclar con otros dos pares de hashes, una y otra vez, hasta obtener un único valor de hash, que sería la raíz del árbol. Con ese valor hash final, conocido como raíz Merkle, se pueden buscar las transacciones originales o los valores hash que las generaron, incluidos los primeros bloques de la blockchain.
  • Nonce: un nonce (que significa “número que solo se usa una vez”) es un número utilizado en la minería de Bitcoin. Los mineros de la cadena de bloques están resolviendo el nonce que, al agregarlo al hash del bloque, produce un hash repetido; al hacerlo, resuelven el rompecabezas de minería.

Por otra parte, el cuerpo del bloque se encarga de las transacciones, incluidas sus entradas y salidas. En la siguiente sección se ampliará el modelo de datos de las transacciones, con énfasis en las entradas y salidas, ya que su relación permite comprender la creación de transacciones propias. No importa qué blockchain esté en funcionamiento, recuerde que las cadenas de bloques son sistemas transaccionales.

Transacciones

Entradas y salidas

Las transacciones codifican la transferencia de valor entre los participantes del sistema. Más detalladamente, una transacción es una estructura de datos que codifica una transferencia de valor desde una fuente de fondos, llamada “entrada”, hacia un destino, llamado “salida”.

Las entradas de una transacción son únicamente las salidas no gastadas de otra transacción. Todas las entradas hacen referencia a una salida. Recuerde que las salidas no utilizadas se denominan UTXO (por sus siglas en inglés). La siguiente imagen nos ilustra la relación entre las entradas y las salidas de un par de transacciones:

Entradas y salidas de transacciones

Conceptualice la flecha como un puntero hacia las entradas que hacen referencia a las salidas de las que provienen. Esto es similar a los punteros en una lista enlazada. Descubrirá que esta es una notación de flecha estándar: las entradas apuntan hacia sus salidas.

Tiempo para revisar los modelos de datos de las transacciones.

Modelo de datos en las transacciones

Esta es una transacción sin procesar:

0100000001f3f6a909f8521adb57d898d2985834e632374e770fd9e2b98656f1bf1fdfd427010000006b48304502203a776322ebf8eb8b58cc6ced4f2574f4c73aa664edce0b0022690f2f6f47c521022100b82353305988cb0ebd443089a173ceec93fe4dbfe98d74419ecc84a6a698e31d012103c5c1bc61f60ce3d6223a63cedbece03b12ef9f0068f2f3c4a7e7f06c523c3664ffffffff0260e31600000000001976a914977ae6e32349b99b72196cb62b5ef37329ed81b488ac063d1000000000001976a914f76bc4190f3d8e2315e5c11c59cfc8be9df747e388ac00000000

Nada legible para cualquier persona. La siguiente imagen resume el modelo de datos de dicha transacción:

Transaction Data Model

Como se puede observar, la convención de colores nos permite identificar los componentes del modelo de datos de una transacción.

Se aclara que una transacción en la Blockchain de Bitcoin es almacenada en forma de doble hash:

SHA256(SHA256(01000…)) = b138360800cdc72248c3ca8dfd06de85913d1aac7f41b4fa54eb1f5a4a379081

Para explorar los contenidos de una transacción de forma legible, se puede utilizar BlockCypher. Ahora bien, es tiempo de desglozar la transacción en bruto:

Raw Transaction Breakdown

  • Versión: todas las transacciones incluyen información sobre el número de versión de Bitcoin para que sepamos qué reglas se aplican a esta transacción.
  • Recuento de entradas: cuántas entradas se usaron para esta transacción

Datos almacenados en la información de entrada

  • Hash de salida anterior: todas las entradas hacen referencia a una salida (UTXO). Esto apunta de nuevo a la transacción que contiene la UTXO que se gastará en esta entrada. El valor del hash de este UTXO se guarda aquí en orden inverso.
  • Índice de salida anterior: la transacción puede tener más de un UTXO al que se hace referencia mediante su número de índice. El primer índice es 0.
  • Tamaño del script de desbloqueo: tamaño del script de desbloqueo en bytes. Script de desbloqueo: es el hash del script de desbloqueo que cumple con las condiciones del script de bloqueo de UTXO.
  • Número de secuencia: es una función obsoleta de Bitcoin, configurada por defecto en ffffffff.

Recuento de salidas: indica cuántas salidas se produjeron a partir de esta transacción.

Datos almacenados en la información de salida

  • Cantidad: la cantidad de Bitcoin generada, expresada en satoshis (la unidad más pequeña de Bitcoin). 10^8 Satoshis = 1 Bitcoin.
  • Tamaño del script de bloqueo: tamaño, en bytes, del script de bloqueo.
  • Script de bloqueo: este es el hash del script de bloqueo que especifica las condiciones que deben cumplirse para gastar esta salida.
  • Tiempo de bloqueo: el campo de tiempo de bloqueo indica la hora más temprana, o el bloque más temprano, en el que se puede agregar una transacción a la cadena de bloques. Si el tiempo de bloqueo no es cero y es inferior a 500 millones, se interpreta como la altura del bloque y los mineros deben esperar hasta alcanzar esa altura de bloque antes de intentar agregarlo a un bloque. Si el tiempo de bloqueo es superior a 500 millones, se interpreta como una marca de tiempo UNIX, que indica el número de segundos transcurridos desde el 1 de enero de 1970. Por lo general, es 0, lo que significa que debe confirmarse lo antes posible.

Opcodes

Los códigos de operación, abreviados como opcodes, forman parte del conjunto de instrucciones de Bitcoin y suman aproximadamente 80. Hay que tener presente que el scripting de Bitcoin es un lenguaje basado en pila y que sus opcodes permiten interactuar con la pila de datos. Las instrucciones más comunes para el manejo de pilas son PUSH y POP, que empujan y retiran elementos de la pila, respectivamente. Todos estos códigos empiezan con el prefijo OP_ y con la acción a ejecutar. La lista de opcodes de Bitcoin la puede consultar en aquí. Ahora bien, para familiarizarse con la ejecución de los opcodes se explica el siguiente script:

2 6 OP_ADD 8 OP_EQUAL

El resultado de ese script es el valor booleano TRUE. A continuación, se comparte el paso a paso de la ejecución del script. Es importante señalar que los scripts se ejecutan de izquierda a derecha:

  1. PUSH 2 empuja el 2 en la pila [2]
  2. PUSH 6 empuja el 6 en la pila [2 6]
  3. OP_ADD retira el 2 y el 6 de la pila; los suma para obtener el 8 y lo empuja a la pila [8]
  4. PUSH 8 empuja el 8 en la pila [8 8]
  5. OP_EQUAL 8 retira ambos 8, los compara para la evaluación y empuja TRUE a la pila [TRUE].

Estos scripts se usan para bloquear las salidas de las transacciones. La parte del 6 OP_ADD 8 OP_EQUAL se conoce como el locking script, mientras que el 2 se conoce como el unlocking script. Si la ejecución del script es TRUE, significa que la transacción es válida y el UTXO puede ser gastado por cualquier minero que identifique que el número 2 desbloquea el script. Este ejemplo es para familiarizarse con el proceso, ya que en la aplicación real de Bitcoin las llaves públicas se incluyen como parte del script, teniendo algo como:

  OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG

En donde es el unlocking script y OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG es el locking script.

Atributos de un script

Los dos atributos de un script son: incompletud de Turing y la yerificación sin estado

Cuando se dice que un script es incompleto de Turing, significa que no admite bucles ni estructuras de control complejas. Por otra parte, es completamente determinístico: se sabe cuándo y cómo terminará el programa. Así se elimina el miedo a que la ejecución de un script termine en un bucle infinito o rompa la cadena de bloques. Por último, al tener un lenguaje limitado, se evita que la validación de transacciones sea objetivo de ataques, ya que se realiza mediante un sistema simple y seguro.

En cuanto a la verificación sin estado, el script debe contar con toda la información necesaria para su ejecución y no debe guardar ningún estado antes ni después de ejecutarlo. Así se garantiza que el mismo script puede utilizarse en diferentes sistemas.

Ciclo de vida de una transacción en Blockchain

Ahora que se conocen las partes de una transacción cruda, es hora de usar el protocolo de Bitcoin para construir nuestra propia transacción cruda.

Como se ha visto, la billetera principal de Bitcoin permite aprovechar muchas funciones del protocolo de Bitcoin, pero estas se ven limitadas al acceder a través de una interfaz gráfica de usuario.

Para aprovechar al máximo el potencial del protocolo, se debe omitir la interfaz gráfica de usuario y trabajar directamente con él.

Esto te ayudará a saber qué comandos implementar al crear tu propia cadena de bloques privada que pueda realizar transacciones y asegurar los bloques con una firma digital.

A continuación, se presentan los pasos que sigue una transacción en Blockchain.

  1. Ver todos los UTXO confirmados no gastados en la billetera.
  2. ver los detalles de un UTXO específico.
  3. Crear una transacción sin procesar.
  4. Decodificar la transacción sin procesar para verificar que se haya realizado correctamente.
  5. Firmar la transacción sin procesar.
  6. Enviar la transacción sin procesar a la red.
  7. Consultar el TxID de la transacción que enviamos.

Una cosa a tener en cuenta es que estos pasos siguen el flujo del ciclo de vida de la transacción.

Insertar datos en transacciones

El blockchain es una base de datos en la que no es posible editar ni borrar la información. Las acciones disponibles son leer, adjuntar y validar los datos.

Esta característica aporta beneficios al registro histórico preciso y agiliza la lectura y la escritura de dichos registros. No obstante, hay una desventaja: se debe llegar a un consenso sobre los registros.

Una pregunta válida es si, además de los datos transaccionales, se pueden almacenar otros tipos de datos en la Blockchain. El protocolo, como tal, no está diseñado para almacenar datos no transaccionales. No obstante, para agregar otros tipos de datos, estos deben incluirse en la transacción. Por eso, Blockchain se utiliza para el manejo de datos financieros.

El hecho de incluir datos de almacenamiento en las transacciones nos expone a riesgos y problemas. Por eso, hay que tener en cuenta varias consideraciones antes de almacenar datos en una blockchain pública.

Incrustar datos en la Blockchain

En los primeros días de la comunidad de Bitcoin, los miembros probaron diferentes formas de aprovecharse de la irreversibilidad de los datos almacenados en la blockchain.

Resolvieron incluir la información en el valor del atributo scriptSig para no alterar el resultado final del script ejecutado. Los usuarios pueden tomar estos datos, convertirlos en un hash y luego incorporarlo a la salida.

Ahora podemos manejar cualquier tipo de datos, desde fotografías de Nelson Mandela hasta notas almacenadas de forma permanente en la blockchain, para los mineros que aman tenerlas.

No obstante, este enfoque despertó a algunos objetores que argumentaban que dicho almacenamiento sobrecargaba la cadena de bloques porque forzaba a los nodos de Bitcoin a pagar el costo de almacenar datos que no deberían pagar, ya que los UTXO tienen scripts de bloqueo que no pueden desbloquearse, lo que impide que el UTXO se remueva y hace que dicha información se almacene para siempre en los nodos de Bitcoin.

Es por esta razón que los desarrolladores de Bitcoin introdujeron el opcode OP_RETURN , que permite usar 40 bytes en una transacción prescindible; de esta forma, se evita la necesidad de almacenarlos en el conjunto de UTXO. A pesar de que las salidas de OP_RETURN se registran en la cadena de bloques en memoria, no se almacenan en el conjunto UXTO, lo que evita la carga adicional del fondo de memoria del UXTO.

Los datos que usan OP_RETURN se guardan en el script en el formato OP_RETURN. A menudo es el resultado de un hash SHA-256. La siguiente imagen especifica en qué parte de la transacción se incorpora el OP_RETURN:

Raw Transaction OP_RETURN

Los datos resaltados en la imagen están hasheados en formato hexadecimal y pueden convertirse en un string que muestra el resultado final “charley loves heidi”.

Hemos visto cómo es posible incrustar datos en la blockchain, y una pregunta válida es si este proceso es ético y si debería hacerse. Este tema se desarrollará en la siguiente publicación relacionada con las blockchains públicas y privadas.