Glosario / Minería y consenso
Bloque serializado
- ¿Qué es un bloque serializado?
- Un bloque serializado es la cadena de bytes exacta en la que se convierte un bloque en la red o en disco: el encabezado de 80 bytes, un recuento de transacciones y después cada transacción en orden.
Se especifica en el BIP-144.
La serialización es lo que convierte un bloque abstracto en algo de lo que se puede calcular el hash y que se puede enviar y almacenar. El bloque génesis se serializa en 285 bytes: 80 para el encabezado, 1 para el recuento de transacciones y 204 para su única transacción coinbase. Si alguna vez ha pegado hexadecimal en bruto en un explorador de bloques o ha ejecutado la llamada RPC getblock con el parámetro verbosity en 0, esto es lo que estaba viendo.
Cómo funciona
En un bloque serializado hay tres piezas colocadas una detrás de otra, y solo la primera tiene una longitud fija.
El encabezado siempre ocupa 80 bytes, en este orden: una versión de 4 bytes, el hash de 32 bytes del encabezado anterior, la raíz de Merkle de 32 bytes, una marca de tiempo de 4 bytes, el campo nBits de 4 bytes que codifica el objetivo y un nonce de 4 bytes. Después viene el número de transacciones, escrito en compactSize, un entero de longitud variable que ocupa 1 byte para recuentos inferiores a 253 y hasta 9 bytes para cualquier valor enorme. Luego, las propias transacciones, cada una serializada por completo, con la transacción coinbase en primer lugar.
Desde el BIP144, el mismo bloque tiene dos serializaciones válidas. La forma sin datos de testigo deja fuera por completo los testigos y es la que espera el software anterior a 2017. La forma completa los incluye y marca cada transacción que lleva testigo con un byte 0x00 seguido de un byte indicador 0x01, en el lugar donde de otro modo iría el recuento de entradas. Ambas codifican el mismo bloque y ambas producen el mismo hash de bloque, porque el hash solo abarca esos 80 bytes del encabezado, y la raíz de Merkle que va dentro de ellos fija los ID de transacción, que se calculan a partir de la codificación sin datos de testigo. Esa separación es el significado literal de SegWit (testigo segregado).
Hay una costumbre que confunde a todo el mundo al menos una vez: los enteros de varios bytes se escriben en little endian (el byte menos significativo primero), así que la marca de tiempo 0x495FAB29 aparece en la red como 29 ab 5f 49, y los hash se muestran en el orden inverso al de sus bytes serializados. El hash de bloque que usted copia de un explorador no es la secuencia de bytes que está en el archivo.
Dónde aparece
Los bloques serializados viajan por la red entre pares dentro de un mensaje block. Cada mensaje lleva primero un sobre de 24 bytes: 4 bytes mágicos de red, f9beb4d9 en la mainnet, un nombre de comando de 12 bytes, 4 bytes con la longitud de la carga útil y una suma de comprobación de 4 bytes tomada de los cuatro primeros bytes de un doble SHA-256 calculado sobre la carga útil. Bitcoin Core limita la carga útil de cualquier mensaje a 4.000.000 bytes, un límite de la red y no de consenso.
Los mismos bytes acaban en su disco. Bitcoin Core añade los bloques a archivos llamados blk00000.dat y sucesivos, cada uno limitado a 128 MiB, con los mismos bytes mágicos y un prefijo de longitud antes de cada bloque, para que el archivo pueda escanearse de forma lineal. El bloque génesis es la excepción: está compilado en el software como una constante en lugar de descargarse, y eso lo convierte en el ancla con la que un nodo que se sincroniza compara todo lo demás.
En el uso diario, la serialización aparece a través de getblock con verbosity en 0, en la pestaña de datos en bruto o en hexadecimal de la mayoría de los exploradores y dentro de herramientas que permiten decodificar un bloque a mano. Quien verifica que un explorador le dijo la verdad acaba aquí, porque la cadena hexadecimal es la única representación que nadie ha reformateado.
Bloque serializado frente a bloque
Un bloque es el objeto; un bloque serializado es una de sus codificaciones. La distinción era meramente formal hasta 2017, cuando SegWit dio a cada bloque dos codificaciones válidas de longitudes distintas, de modo que el tamaño de un bloque pasó a ser una pregunta que hay que matizar. Bitcoin Core la responde de tres maneras en una sola respuesta RPC: el campo size para la serialización completa, strippedsize para la que no lleva datos de testigo y weight para la cifra que las reglas hacen cumplir en realidad.