El protocolo bitcoin: entendiendo la arquitectura de la red

Valoración: 2.73 (937 votos)

Bitcoin se basa en una arquitectura de red peer-to-peer (P2P) construida sobre Internet. El término "peer-to-peer" significa que las computadoras que participan en la red son iguales entre sí, sin nodos especiales, y comparten la responsabilidad de proporcionar servicios de red.

Tabla de Contenido

Red P2P y Descentralización

La red de Bitcoin es una red de malla con una topología "plana". No hay servidor, servicio centralizado o jerarquía. Los nodos en una red P2P proporcionan y consumen servicios al mismo tiempo, con la reciprocidad como incentivo para la participación. Esto la convierte en una red inherentemente resistente, descentralizada y abierta. La descentralización es un principio fundamental del diseño de Bitcoin, solo alcanzable con una red de consenso P2P plana y descentralizada.

El Protocolo Bitcoin

El término "red Bitcoin" se refiere al conjunto de nodos que ejecutan el protocolo Bitcoin P2P. Además del protocolo Bitcoin P2P, existen otros protocolos como Stratum, utilizados para la minería y carteras ligeras o móviles. Estos protocolos adicionales son proporcionados por servidores de enrutamiento de puerta de enlace que acceden a la red Bitcoin utilizando el protocolo Bitcoin P2P y luego lo extienden a nodos que ejecutan otros protocolos.

Tipos de Nodos y sus Roles

Aunque los nodos en la red Bitcoin P2P son iguales, pueden asumir diferentes roles según la funcionalidad que brinden. Un nodo Bitcoin es una colección de funciones: enrutamiento, base de datos de blockchain, minería y servicios de cartera.

  • Nodos Completos: Mantienen una copia completa y actualizada de la blockchain. Pueden verificar cualquier transacción de forma autónoma y autoritativa, sin referencias externas.
  • Nodos SPV (Lightweight): Mantienen solo un subconjunto de la blockchain y verifican las transacciones utilizando una verificación de pago simplificada (SPV). No almacenan la blockchain completa.
  • Nodos de Minería: Compiten para crear nuevos bloques ejecutando hardware especializado para resolver el algoritmo de prueba de trabajo. Algunos nodos de minería también son nodos completos, mientras que otros son nodos ligeros que participan en la minería en grupo.
  • Carteras: Pueden ser parte de un nodo completo (como los clientes de Bitcoin de escritorio). Sin embargo, muchas carteras, especialmente las que se ejecutan en dispositivos con recursos limitados, son nodos SPV.

La Red Bitcoin Extendida

La red Bitcoin extendida incluye la red que ejecuta el protocolo Bitcoin P2P, así como nodos que ejecutan protocolos especializados. Se compone de:

  • Red Bitcoin P2P: Contiene entre 7,000 y 10,000 nodos que ejecutan diferentes versiones del cliente de referencia de Bitcoin (Bitcoin Core) y algunos cientos que ejecutan otras implementaciones del protocolo Bitcoin P2P.
  • Servidores de Grupos de Minería: Se conectan a nodos de minería en grupo y a la red principal de Bitcoin.
  • Clientes de Carteras Ligeras: No mantienen una copia completa de la blockchain. Conectan con la red a través de servidores de puerta de enlace.
  • Enrutadores de Bordo: Nodos completos que actúan como enrutadores de borde de red, permitiendo la construcción de servicios como intercambios, carteras, exploradores de bloques y procesamiento de pagos comerciales.

Descubrimiento de la Red

Cuando un nuevo nodo se inicia, debe descubrir otros nodos Bitcoin en la red para participar. El proceso comienza con la búsqueda de al menos un nodo existente. Un nuevo nodo se conecta a un nodo conocido estableciendo una conexión TCP (generalmente al puerto 8333). Luego, se inicia un "handshake" (ver Figura 6-4) transmitiendo un mensaje de versión que contiene información básica de identificación, incluyendo:

  • PROTOCOL_VERSION: Define la versión del protocolo Bitcoin P2P que el cliente habla (por ejemplo, 70002).
  • nLocalServices: Lista de servicios locales admitidos por el nodo (actualmente solo NODE_NETWORK).
  • nTime: Hora actual.
  • addrYou: Dirección IP del nodo remoto tal como lo ve el nodo actual.
  • addrMe: Dirección IP del nodo local, tal como lo descubrió el nodo local.
  • subver: Subversión que muestra el tipo de software que se ejecuta en el nodo (por ejemplo, "Satoshi:0.1/").
  • BestHeight: Altura del bloque de la blockchain del nodo (ver GitHub para un ejemplo del mensaje de red de versión).

El nodo par responde con "verack" para confirmar y establecer una conexión, y opcionalmente envía su propio mensaje de versión si desea reciprocar la conexión y conectarse como par.

Para encontrar pares, los nodos pueden utilizar:

  • Semillas DNS: Servidores DNS que proporcionan una lista de direcciones IP de nodos Bitcoin. Algunos proporcionan una lista estática, mientras que otros son implementaciones personalizadas de BIND que devuelven un subconjunto aleatorio de una lista de direcciones de nodos Bitcoin recopiladas por un rastreador o un nodo Bitcoin de larga duración.
  • Introducciones: Un nodo que no conoce la red necesita la dirección IP de al menos un nodo Bitcoin para establecer conexiones. El argumento de línea de comandos "seednode" se puede usar para conectarse a un nodo solo para obtener introducciones.

Una vez que se establecen una o más conexiones, el nuevo nodo envía un mensaje "addr" con su propia dirección IP a sus vecinos. Los vecinos, a su vez, reenvían el mensaje "addr" a sus vecinos, asegurando que el nodo recién conectado se vuelva conocido y esté mejor conectado. Además, el nodo recién conectado puede enviar "getaddr" a sus vecinos, pidiéndoles que devuelvan una lista de direcciones IP de otros pares.

Nodos Completos

Los nodos completos mantienen una blockchain completa con todas las transacciones. En los primeros años de Bitcoin, todos los nodos eran nodos completos. Sin embargo, en los últimos años se han introducido nuevas formas de clientes de Bitcoin que no mantienen una blockchain completa, sino que funcionan como clientes ligeros. Los nodos completos mantienen una copia completa y actualizada de la blockchain Bitcoin, que construyen y verifican independientemente, comenzando con el primer bloque (bloque génesis) y avanzando hasta el último bloque conocido en la red. Un nodo completo puede verificar cualquier transacción de forma independiente y autoritativa, sin depender de ningún otro nodo o fuente de información.

Ejecutar un nodo completo ofrece la experiencia pura de Bitcoin: verificación independiente de todas las transacciones sin necesidad de confiar en otros sistemas. Se necesita un espacio de almacenamiento persistente de 20 gigabytes o más para almacenar la blockchain completa. Ese es el precio de la independencia completa y la libertad de la autoridad central.

Intercambio de "Inventario"

Una vez que un nodo completo se conecta a pares, intenta construir una blockchain completa. Si es un nodo nuevo y no tiene una blockchain, solo conoce un bloque, el bloque génesis, que está integrado estáticamente en el software del cliente. A partir del bloque #0 (el bloque génesis), el nuevo nodo deberá descargar cientos de miles de bloques para sincronizarse con la red y restablecer la blockchain completa.

El proceso de sincronización de la blockchain comienza con el mensaje de versión, que contiene "BestHeight", la altura actual de la blockchain del nodo (número de bloques). Un nodo ve los mensajes de versión de sus pares, sabe cuántos bloques tienen cada uno y puede comparar con cuántos bloques tiene en su propia blockchain. Los nodos conectados intercambian un mensaje "getblocks" que contiene el hash (huella digital) del bloque superior en su blockchain local. Uno de los pares podrá identificar el hash recibido como perteneciente a un bloque que no está en la parte superior, sino que pertenece a un bloque más antiguo, deduciendo así que su propia blockchain local es más larga que la de su par. El par que tiene la blockchain más larga tiene más bloques que el otro nodo y puede identificar qué bloques necesita el otro nodo para "ponerse al día". Identificará los primeros 500 bloques para compartir y transmitirá sus hashes usando un mensaje "inv" (inventario). El nodo que falta estos bloques los recuperará mediante una serie de mensajes "getdata" que solicitan los datos completos del bloque e identifican los bloques solicitados usando los hashes del mensaje "inv".

A medida que cada bloque se recibe, se agrega a la blockchain. A medida que la blockchain local se construye gradualmente, se solicitan y reciben más bloques, y el proceso continúa hasta que el nodo se pone al día con el resto de la red. Este proceso de comparar la blockchain local con los pares y recuperar los bloques faltantes ocurre cada vez que un nodo se desconecta durante un período de tiempo. Ya sea que un nodo haya estado fuera de línea durante unos minutos y le falten algunos bloques, o un mes y le falten algunos miles de bloques, comienza enviando "getblocks", recibe una respuesta "inv" y comienza a descargar los bloques faltantes.

Verificación de Pago Simplificada (SPV)

No todos los nodos tienen la capacidad de almacenar la blockchain completa. Muchos clientes de Bitcoin están diseñados para funcionar en dispositivos con limitaciones de espacio y energía, como teléfonos inteligentes, tabletas o sistemas integrados. Para tales dispositivos, se utiliza un método de verificación de pago simplificado (SPV) para permitirles operar sin almacenar la blockchain completa. Estos tipos de clientes se denominan clientes SPV o clientes ligeros.

Los nodos SPV descargan solo los encabezados de bloque y no descargan las transacciones incluidas en cada bloque. La cadena resultante de bloques, sin transacciones, es 1,000 veces más pequeña que la blockchain completa. Los nodos SPV no pueden construir una imagen completa de todos los UTXO disponibles para gastar porque no conocen todas las transacciones en la red. Los nodos SPV verifican las transacciones usando una metodología ligeramente diferente que se basa en los pares para proporcionar vistas parciales de partes relevantes de la blockchain a pedido.

La verificación de pago simplificada verifica las transacciones por referencia a su profundidad en la blockchain en lugar de su altura. Mientras que un nodo de blockchain completo construirá una cadena completamente verificada de miles de bloques y transacciones que llegan a la blockchain (en el tiempo) hasta el bloque génesis, un nodo SPV verificará la cadena de todos los bloques (pero no todas las transacciones) y vinculará esa cadena a la transacción de interés. Por ejemplo, al examinar una transacción en el bloque 300,000, un nodo completo vincula los 300,000 bloques al bloque génesis y construye una base de datos completa de UTXO, estableciendo la validez de la transacción al confirmar que el UTXO permanece sin gastar. Un nodo SPV no puede validar si el UTXO está sin gastar. En cambio, el nodo SPV establecerá un enlace entre la transacción y el bloque que la contiene, utilizando una ruta merkle (ver Árboles Merkle). Luego, el nodo SPV espera hasta que ve los seis bloques 300,001 a 300,006 apilados sobre el bloque que contiene la transacción y lo verifica estableciendo su profundidad debajo de los bloques 300,006 a 300,00El hecho de que otros nodos en la red hayan aceptado el bloque 300,000 y luego hayan hecho el trabajo necesario para producir seis bloques más encima de él es una prueba, por poder, de que la transacción no fue un gasto doble. Un nodo SPV no puede ser persuadido de que una transacción existe en un bloque cuando la transacción en realidad no existe. El nodo SPV establece la existencia de una transacción en un bloque solicitando una prueba de ruta merkle y validando la prueba de trabajo en la cadena de bloques. Sin embargo, la existencia de una transacción puede "ocultarse" a un nodo SPV. Un nodo SPV puede definitivamente probar que una transacción existe, pero no puede verificar que una transacción, como un gasto doble del mismo UTXO, no existe porque no tiene un registro de todas las transacciones. Esta vulnerabilidad se puede utilizar en un ataque de denegación de servicio o en un ataque de gasto doble contra nodos SPV. Para defenderse de esto, un nodo SPV necesita conectarse aleatoriamente a varios nodos, para aumentar la probabilidad de que esté en contacto con al menos un nodo honesto. Esta necesidad de conectarse aleatoriamente significa que los nodos SPV también son vulnerables a los ataques de partición de red o ataques Sybil, donde están conectados a nodos falsos o redes falsas y no tienen acceso a nodos honestos o a la red Bitcoin real. Para la mayoría de los propósitos prácticos, los nodos SPV bien conectados son lo suficientemente seguros, logrando el equilibrio adecuado entre las necesidades de recursos, la practicidad y la seguridad. Sin embargo, para una seguridad infalible, nada supera la ejecución de un nodo de blockchain completo.

Filtros Bloom

Un filtro Bloom es un filtro de búsqueda probabilístico, una forma de describir un patrón deseado sin especificarlo exactamente. Los filtros Bloom ofrecen una forma eficiente de expresar un patrón de búsqueda mientras protegen la privacidad. Son utilizados por los nodos SPV para pedir a sus pares las transacciones que coincidan con un patrón específico, sin revelar exactamente qué direcciones están buscando.

Los filtros Bloom se implementan como una matriz de tamaño variable de N dígitos binarios (un campo de bits) y un número variable de M funciones hash. Las funciones hash están diseñadas para producir siempre una salida que esté entre 1 y N, correspondiente a la matriz de dígitos binarios. Las funciones hash se generan de forma determinista, de modo que cualquier nodo que implemente un filtro Bloom siempre utilizará las mismas funciones hash y obtendrá los mismos resultados para una entrada específica. Al elegir diferentes longitudes (N) de filtros Bloom y un número diferente (M) de funciones hash, el filtro Bloom se puede ajustar, variando el nivel de precisión y, por lo tanto, la privacidad. En la Figura 6-8, se utiliza una matriz muy pequeña de 16 bits y un conjunto de tres funciones hash para demostrar cómo funcionan los filtros Bloom.

Los filtros Bloom se utilizan para filtrar las transacciones (y los bloques que las contienen) que un nodo SPV recibe de sus pares. Los nodos SPV crearán un filtro que coincida solo con las direcciones que se encuentran en la cartera del nodo SPV. Luego, el nodo SPV enviará un mensaje "filterload" al par, que contiene el filtro Bloom que se utilizará en la conexión. Una vez establecido un filtro, el par probará las salidas de cada transacción contra el filtro Bloom. Solo las transacciones que coinciden con el filtro se envían al nodo. En respuesta a un mensaje "getdata" del nodo, los pares enviarán un mensaje "merkleblock" que contiene solo los encabezados de bloque para los bloques que coinciden con el filtro y una ruta merkle (ver Árboles Merkle) para cada transacción coincidente. Luego, el par también enviará mensajes "tx" que contienen las transacciones coincidentes con el filtro. El nodo que configura el filtro Bloom puede agregar patrones al filtro de forma interactiva enviando un mensaje "filteradd". Para borrar el filtro Bloom, el nodo puede enviar un mensaje "filterclear". Debido a que no es posible eliminar un patrón de un filtro Bloom, un nodo tiene que borrar y reenviar un nuevo filtro Bloom si ya no se desea un patrón.

Pools de Transacciones

Casi todos los nodos de la red Bitcoin mantienen una lista temporal de transacciones no confirmadas llamada pool de memoria, mempool o pool de transacciones. Los nodos utilizan este pool para hacer un seguimiento de las transacciones que son conocidas por la red pero aún no están incluidas en la blockchain. Por ejemplo, un nodo que tiene una cartera de usuario utilizará el pool de transacciones para hacer un seguimiento de los pagos entrantes a la cartera del usuario que se han recibido en la red pero aún no se han confirmado. A medida que se reciben y verifican las transacciones, se agregan al pool de transacciones y se retransmiten a los nodos vecinos para propagarse en la red. Algunas implementaciones de nodos también mantienen un pool separado de transacciones huérfanas. Si las entradas de una transacción se refieren a una transacción que aún no se conoce, como un padre faltante, la transacción huérfana se almacenará temporalmente en el pool de huérfanos hasta que llegue la transacción padre. Cuando una transacción se agrega al pool de transacciones, se comprueba el pool de huérfanos para ver si hay huérfanos que hacen referencia a las salidas de esta transacción (sus hijos). Cualquier huérfano coincidente se valida. Si es válido, se elimina del pool de huérfanos y se agrega al pool de transacciones, completando la cadena que comenzó con la transacción padre. A la luz de la transacción recién agregada, que ya no es un huérfano, el proceso se repite recursivamente buscando más descendientes, hasta que no se encuentran más descendientes. A través de este proceso, la llegada de una transacción padre activa una reconstrucción en cascada de una cadena completa de transacciones interdependientes al reunir los huérfanos con sus padres a lo largo de la cadena. Tanto el pool de transacciones como el pool de huérfanos (donde se implementan) se almacenan en la memoria local y no se guardan en el almacenamiento persistente; más bien, se llenan dinámicamente a partir de los mensajes de red entrantes. Cuando un nodo se inicia, ambos pools están vacíos y se llenan gradualmente con nuevas transacciones recibidas en la red. Algunas implementaciones del cliente de Bitcoin también mantienen una base de datos UTXO o un pool UTXO, que es el conjunto de todas las salidas no gastadas en la blockchain. Aunque el nombre "pool UTXO" suena similar al pool de transacciones, representa un conjunto de datos diferente. A diferencia de los pools de transacciones y huérfanos, el pool UTXO no se inicializa vacío, sino que contiene millones de entradas de salidas de transacciones no gastadas, incluidas algunas que datan de 200El pool UTXO puede alojarse en la memoria local o como una tabla de base de datos indexada en el almacenamiento persistente. Mientras que los pools de transacciones y huérfanos representan la perspectiva local de un solo nodo y pueden variar significativamente de un nodo a otro dependiendo de cuándo se inició o reinició el nodo, el pool UTXO representa el consenso emergente de la red y, por lo tanto, variará poco entre los nodos. Además, los pools de transacciones y huérfanos solo contienen transacciones no confirmadas, mientras que el pool UTXO solo contiene salidas confirmadas.

Si quieres conocer otros artículos parecidos a El protocolo bitcoin: entendiendo la arquitectura de la red puedes visitar la categoría Finanzas / Inversiones.

Subir