Leer el tráfico de red de Bitcoin
Una captura histórica de Wireshark conecta el registro con la red. Reconstruimos la envoltura V1 de 24 bytes, verificamos la suma de comprobación de un contenido vacío, seguimos peticiones de bloques y desglosamos un bloque con una sola transacción. Después distinguimos delimitación TCP, análisis de mensajes, validación de bloques y elección de cadena, y explicamos qué cambia con el transporte cifrado V2.
Un bloque de Bitcoin no viaja solo. Se serializa, se envuelve en un mensaje del protocolo, se escribe en el flujo de bytes de una conexión y la pila de red lo divide en paquetes. Un analizador reconstruye esas capas para que podamos leerlas.
Esta visión por capas sirve mucho más allá de Bitcoin. Muchos errores de protocolo nacen de confundir un paquete con un mensaje, una suma de comprobación con autenticación o los datos recibidos de un nodo con datos ya validados por la aplicación.
En la parte anterior examinamos un bloque guardado en disco. Aquí usamos capturas históricas de Wireshark del transporte V1 de Bitcoin. Contienen bloques antiguos intercambiados por un nodo posterior: la fecha del bloque no es la de la captura. Mantendremos esa distinción y no trataremos capturas independientes como si fueran un único intercambio continuo.

Sesión original de Wireshark con mensajes de Bitcoin en la lista de paquetes. Ampliar imagen.
5.1 Establecer la conexión antes de intercambiar bloques
Un nodo necesita primero la dirección de otro. Puede obtener candidatos de su base de datos de pares, de otros nodos o de mecanismos de arranque como las semillas DNS. El descubrimiento proporciona destinos a los que conectarse; no les concede autoridad sobre el registro.
En el intercambio V1 que estudiamos, los nodos abren una conexión TCP e intercambian mensajes version con información sobre el protocolo y sus servicios. Confirman el intercambio con verack. Según las funciones admitidas, pueden aparecer otros mensajes de negociación alrededor de este proceso.
Los mensajes no autentican una identidad humana ni certifican que el otro nodo sea honrado. El establecimiento de la conexión permite una conversación de protocolo utilizable. Seguimos comprobando lo que envía el otro extremo.
Un nodo también puede mantener muchas conexiones simultáneas. En la lista de paquetes, dos filas consecutivas de Bitcoin pueden corresponder a máquinas remotas diferentes. Antes de deducir una conversación, hay que filtrar por conexión o flujo TCP y comprobar la dirección, los identificadores solicitados y el contenido de las respuestas. La guía P2P distingue el descubrimiento de nodos, el establecimiento de conexiones y la descarga de bloques.
5.2 Decodificar la envoltura de mensajes V1
Un mensaje V1 tiene una cabecera de 24 bytes seguida de un contenido cuya longitud declara la cabecera. La misma envoltura transporta órdenes con cuerpos muy diferentes: verack tiene contenido vacío, mientras que block contiene un bloque serializado.
En la red principal, los bytes de identificación son f9 be b4 d9. La orden se expresa en ASCII; la longitud del contenido es un entero de 32 bits en little-endian. La suma de comprobación son los primeros cuatro bytes del SHA-256 doble del contenido.
La suma detecta daños accidentales o errores de ensamblado. No es una firma ni un código de autenticación: un adversario que modifique el contenido puede recalcularla. Reconocer los bytes de identificación tampoco demuestra la validez de un bloque. Son comprobaciones de análisis y transporte, no decisiones de consenso.
La secuencia de identificación es la misma que vimos en el registro histórico de disco, pero las estructuras que la rodean son distintas. Un registro de disco tiene identificación, tamaño y bloque serializado. Un mensaje de red V1 añade una orden y una suma de comprobación. Ninguna de las dos envolturas entra en el hash de prueba de trabajo del bloque.

Captura original que resalta la identificación de la red principal en la envoltura V1. Ampliar imagen.
5.3 Comprobar un mensaje verack completo
El mensaje verack capturado cabe por completo en su cabecera de 24 bytes:
f9 be b4 d9
76 65 72 61 63 6b 00 00 00 00 00 00
00 00 00 00
5d f6 e0 e2Los seis bytes no nulos de la orden forman verack. Otros seis ceros completan ese campo. Los cuatro ceros siguientes indican una longitud de contenido igual a cero. La suma de comprobación no es cero: el hash de una secuencia vacía no es un resultado vacío.
Podemos verificar el ejemplo completo sin un nodo ni un analizador de paquetes:
from hashlib import sha256
from struct import unpack
def hash256(data):
return sha256(sha256(data).digest()).digest()
message = bytes.fromhex("""
f9beb4d9
76657261636b000000000000
00000000
5df6e0e2
""")
magic, command, size, checksum = unpack("<4s12sI4s", message[:24])
payload = message[24:]
assert len(message) == 24
assert magic == bytes.fromhex("f9beb4d9")
assert command == b"verack" + bytes(6)
assert size == len(payload) == 0
assert checksum == hash256(payload)[:4] == bytes.fromhex("5df6e0e2")Esta comprobación tiene un alcance deliberadamente reducido: valida los bytes de este mensaje conocido. Un analizador de flujos necesita además almacenamiento intermedio, límites de longitud y una forma segura de manejar mensajes incompletos o malformados. No debe suponer que una única lectura del socket devuelve exactamente una envoltura.

Captura original de verack. Se pueden contrastar la orden, la longitud cero y la suma del contenido vacío con los bytes anteriores. Ampliar imagen.
5.4 Encontrar el bloque dentro de su respuesta
Otra captura muestra una respuesta block con 216 bytes de contenido, longitud codificada como d8 00 00 00. El campo de orden V1 contiene los cinco bytes de block seguidos de siete ceros. La suma de comprobación mostrada es 29 d9 15 04.
Dentro del contenido, el analizador despliega una cabecera de 80 bytes, un recuento de una transacción y la propia transacción. Así podemos cuadrar los tamaños:
Con la cabecera de red, el mensaje de aplicación ocupa 240 bytes. Estos totales no incluyen las cabeceras de Ethernet, IP ni TCP.

Respuesta original de bloque con la envoltura V1 y la cabecera desplegadas. La fila getdata contigua pertenece a otro nodo; la proximidad no demuestra una relación de petición y respuesta. Ampliar imagen.
La cabecera de esta respuesta corresponde a un bloque de principios de 2009. No es el bloque de julio de 2011 del artículo anterior. Otra captura, con una transacción desplegada, también tiene una cabecera distinta. Podemos usarlas para entender el mismo formato sin mezclar sus bytes en un bloque ficticio.
En esa transacción desplegada, el hash de la transacción anterior está a cero y el índice de salida es ffffffff. Ambos campos identifican una entrada coinbase. El script de ocho bytes es 04ffff001d025d07; la única salida vale 5.000.000.000 satoshis, exactamente 50 BTC, y tiene un script de pago a clave pública de 67 bytes.
Sería incorrecto describirla como un pago ordinario que gasta una transacción anterior de otro usuario: el outpoint nulo es decisivo. Tampoco podemos deducir las comisiones totales solo de los 50 BTC reclamados, porque el minero puede dejar parte de la recompensa sin reclamar. Analizar el registro establece lo que se reclamó; comprobar todo el bloque establece lo que estaba permitido.

Captura original de la transacción desplegada. El outpoint nulo identifica una entrada coinbase y su salida reclama 50 BTC. Su cabecera de bloque es distinta de la captura anterior. Ampliar imagen.
5.5 Leer el flujo, no solo la lista de paquetes
El filtro de visualización bitcoin ayuda a encontrar mensajes V1 decodificados. No significa que cada segmento TCP de la conversación contenga una orden de Bitcoin decodificable por separado. El analizador puede mostrar el protocolo solo en la trama en la que ya hay datos suficientes para reensamblar el mensaje.
TCP transporta un flujo ordenado. Un mensaje de aplicación puede ocupar varios segmentos, y varios mensajes pueden compartir uno. Las retransmisiones, las pérdidas de captura y la llegada fuera de orden complican aún más la lista. El mensaje de 240 bytes anterior aparecía como datos reensamblados, no como una obligación de transmitir un único paquete de ese tamaño.
Una lectura cuidadosa recorre las capas en orden:
- Identificar la conexión y la dirección del mensaje.
- Reensamblar el flujo y comprobar los límites declarados de los mensajes.
- Decodificar la orden, la longitud del contenido y la suma de comprobación.
- Analizar el contenido según el formato de esa orden.
- Aplicar las reglas de validación correspondientes y, para un bloque, contrastar su posición en la cadena conocida.
En una petición getdata, hay que examinar el tipo de inventario y el hash del objeto. Una respuesta block debe corresponder al objeto solicitado en esa conversación. La fila getdata anterior de la captura se dirige a otro nodo, por lo que su mera proximidad no demuestra que causara la respuesta seleccionada. La referencia del protocolo especifica los campos; la captura sigue requiriendo una interpretación cuidadosa.
5.6 Qué cambia con el transporte cifrado
Los esquemas describen el transporte histórico V1 en claro. Bitcoin también dispone de transporte cifrado V2, definido en BIP 324. Un observador pasivo de una conexión V2 no ve los mismos campos de orden legibles ni los mismos bytes de contenido. Usar un decodificador V1 antiguo o filtrar sus órdenes no permite recuperar la misma conversación.
El cifrado de transporte protege el tráfico de una conexión según su diseño. No cifra la cadena pública, no oculta todos los datos observables de la red ni elimina la obligación de validar transacciones. Tampoco otorga por sí solo una identidad real certificada al otro nodo. El registro y el transporte resuelven problemas diferentes.
Volvemos así al principio de diseño de DCoin. El descubrimiento encuentra una fuente. La conexión transporta bytes. La envoltura separa mensajes. La suma comprueba su contenido. Las condiciones de gasto autorizan un cambio de estado. El consenso elige entre historiales válidos. Entender una cadena de bloques resulta más fácil cuando atribuimos a cada mecanismo exactamente lo que puede demostrar.