HotStuff: de cero a estado del arte
Artículo 38 de 47
81%
completado al llegar aquí
Sistemas distribuidosNota de investigación13 min de lectura
Verificación Formal en Consenso: Modelado matemático con TLA+
Qué especifica TLA+ en un consenso BFT, cómo TLC y Apalache buscan contraejemplos a la safety y qué cubren frente a las pruebas tipo Twins.
Ruta HotStuff: 0/47
Prerequisitos recomendados
Si alguno de estos conceptos todavía está medio nebuloso, empieza por aquí. Te ahorra tropiezos y un par de cejas fruncidas.
Safety, liveness y responsiveness en HotStuff
Una separación práctica de las garantías de HotStuff: qué nunca debe pasar, cuándo vuelve a avanzar y por qué responsiveness no significa latencia cero.
Blockchain9 min de lectura→Cómo Twins detecta pérdida de estado y doble voto en protocolos BFT
Cómo Twins duplica réplicas con la misma identidad para emular equivocación y pérdida de estado, y genera escenarios sistemáticos que exponen bugs BFT.
Blockchain11 min de lectura→
Comprende qué significa especificar un consenso BFT en TLA+: estados, acciones, invariantes como 'no hay dos commits en conflicto' y propiedades temporales de liveness, y cómo los model checkers TLC (explícito) y Apalache (simbólico) buscan contraejemplos en instancias finitas del protocolo.
- Safety, liveness y responsiveness en HotStuff (hotstuff-safety-liveness-responsiveness)
- Twins: detección de errores de estado y bloqueos (twins-deteccion-errores-estado-bloqueos)
Detente cuando puedas leer una especificación TLA+ pequeña, señalar su estado inicial, sus acciones y su invariante de safety, y explicar por qué un resultado limpio de TLC vale para la instancia finita que se comprobó y no para todo n.
Glosario de Notación Matemática y Criptográfica
Número de vista o ronda actual. Cada vista tiene un único líder designado.
view = 42Ruta mental de la Verificación Formal con TLA+
1. Especificación
Estados y acciones
2. Propiedades
Safety y liveness
3. Model checking
TLC o Apalache
4. Diseño revisado
Contraejemplo o confianza acotada
Decodificador Didáctico de Conceptos BFT
En palabras simples: Un ensayo de tablero de ajedrez reducido: en lugar de jugar algunas partidas al azar, se recorren todas las posiciones posibles de un tablero pequeño para comprobar que una regla nunca se rompe.
Detalle técnico: Un model checker recorre (explícita o simbólicamente) los estados alcanzables de una especificación con parámetros finitos y reporta una traza si alguno viola el invariante.
Las pruebas de un sistema distribuido tienen un problema de fondo: ejecutan algunas ejecuciones, no todas. En un consenso BFT, el error que importa suele ser una intercalación rara de mensajes, un líder que equivoca y un cambio de vista que llega en el peor momento. La verificación formal ataca ese problema desde otro ángulo: primero se escribe el diseño como un objeto matemático y después se pregunta si una propiedad vale en todos sus estados alcanzables.
Este artículo presenta TLA+ desde la perspectiva de quien diseña protocolos tipo HotStuff. Veremos qué se especifica, cómo se escribe un invariante de safety, por qué liveness requiere fórmulas temporales y supuestos de equidad, en qué se diferencian TLC y Apalache, y por qué todo esto complementa, sin reemplazar, a las pruebas sistemáticas como Twins.
Qué especifica TLA+: estados, acciones y comportamientos
TLA, la lógica temporal de acciones de Lamport, es una lógica para especificar y razonar sobre sistemas concurrentes. Su rasgo distintivo es que el sistema y sus propiedades se escriben en la misma lógica, de modo que "el sistema cumple su especificación" y "un sistema implementa otro" se expresan ambos como implicaciones lógicas. [1]
Los ingredientes son pocos. Un estado asigna valores a las variables. Una acción es una fórmula que relaciona un estado con el siguiente: las variables sin prima hablan del estado actual y las variables con prima (votes') del siguiente. Un comportamiento es una secuencia infinita de estados. La especificación típica tiene la forma , más condiciones de equidad cuando se quiere hablar de progreso: "el primer estado satisface y cada paso es un paso de o deja sin cambios". [1]
Ese último detalle, permitir pasos que no cambian nada (stuttering), no es un tecnicismo. Es lo que permite comparar una especificación abstracta con otra más detallada: un paso del modelo abstracto puede corresponder a varios pasos internos del refinado. Para un consenso, eso significa que se puede escribir primero "las réplicas deciden un único valor" y después demostrar que un protocolo con fases, votos y certificados implementa esa abstracción. [1]
TLA+ es el lenguaje de especificación construido sobre esa lógica. Sus primitivas incluyen booleanos, enteros, funciones, tuplas, registros, secuencias y conjuntos de todo ello, y los diseñadores lo usan para especificar protocolos concurrentes, distribuidos y tolerantes a fallas que tradicionalmente se presentan en pseudocódigo. [2]
Un fragmento ilustrativo: votos, quórums y un invariante
El siguiente módulo es un ejemplo didáctico escrito para este artículo; no proviene de ningún proyecto real ni modela HotStuff completo. Describe una sola ranura de decisión: réplicas correctas que votan a lo sumo una vez, réplicas bizantinas que pueden votar varios bloques y una acción de commit que exige un quórum de más de dos tercios.
---------------------------- MODULE ToyVoting ----------------------------
\* Fragmento ilustrativo: no proviene de ningun proyecto real.
EXTENDS Naturals, FiniteSets
CONSTANTS Replicas, Byz, Blocks
ASSUME Byz \subseteq Replicas /\ 3 * Cardinality(Byz) < Cardinality(Replicas)
VARIABLES votes, committed
vars == <<votes, committed>>
Correct == Replicas \ Byz
Quorums == { Q \in SUBSET Replicas :
3 * Cardinality(Q) > 2 * Cardinality(Replicas) }
Init == /\ votes = [r \in Replicas |-> {}]
/\ committed = {}
CorrectVote(r, b) == /\ r \in Correct
/\ votes[r] = {}
/\ votes' = [votes EXCEPT ![r] = {b}]
/\ UNCHANGED committed
ByzVote(r, b) == /\ r \in Byz
/\ votes' = [votes EXCEPT ![r] = @ \union {b}]
/\ UNCHANGED committed
Commit(b) == /\ \E Q \in Quorums : \A r \in Q : b \in votes[r]
/\ committed' = committed \union {b}
/\ UNCHANGED votes
Next == \E r \in Replicas, b \in Blocks :
CorrectVote(r, b) \/ ByzVote(r, b) \/ Commit(b)
Spec == Init /\ [][Next]_vars
NoConflictingCommits == Cardinality(committed) <= 1
===========================================================================Leámoslo como un diseñador. Init fija el estado inicial: nadie votó y nada está confirmado. CorrectVote codifica la regla de una réplica correcta, que solo vota si aún no lo hizo. ByzVote deja a una réplica bizantina añadir cualquier bloque a su conjunto de votos, que es la forma más simple de modelar la equivocación. Commit permite confirmar un bloque cuando todas las réplicas de algún quórum lo votaron.
NoConflictingCommits es el invariante: en esta ranura única, dos bloques distintos cuentan como conflicto, así que nunca debe haber más de uno confirmado. Es la versión de juguete del teorema de safety de HotStuff, que afirma que dos nodos en conflicto no pueden ser confirmados, cada uno por una réplica correcta. [3] El argumento que el model checker confirmaría por fuerza bruta es el de siempre: dos quórums de más de dos tercios comparten más réplicas de las que el adversario controla, y la réplica correcta del cruce no vota dos veces.
Safety de Basic HotStuff (Teorema 2)
Safety como invariante, liveness como fórmula temporal
Safety dice que algo malo nunca ocurre, y por eso se comprueba estado a estado: si existe un estado alcanzable con dos commits en conflicto, el model checker devuelve la traza que lleva hasta él. Liveness dice que algo bueno acaba ocurriendo, y eso no se puede ver en un estado aislado: hace falta una fórmula temporal sobre comportamientos completos, como , "en algún momento se confirma algo". [1]
La fórmula por sí sola permite que el sistema se quede quieto para siempre, porque los pasos sin cambios siempre están permitidos. Para hablar de progreso hay que añadir supuestos de equidad, como la equidad débil : si una acción queda habilitada de forma continua, termina ejecutándose. [1]
El juguete anterior enseña aquí algo útil. Aun con equidad, la liveness falla: con cuatro réplicas, una bizantina y dos bloques, las tres correctas pueden repartir sus votos dos contra uno y la bizantina puede negarse a completar el quórum de ninguno de los dos. Nada viola safety, pero nada se confirma nunca. Ese contraejemplo es exactamente la razón por la que los protocolos reales tienen vistas, líderes y cambios de vista.
HotStuff formula su liveness con esa forma: después de GST existe un periodo acotado tal que, si todas las réplicas correctas permanecen en la vista durante ese periodo y el líder de es correcto, se alcanza una decisión. [3] Especificar eso en TLA+ obliga a modelar tiempo o, de forma más abstracta, a declarar como supuesto de equidad que eventualmente hay una vista suficientemente larga con líder correcto. Ese supuesto queda escrito y revisable, en lugar de esconderse en un comentario del código.
TLC y Apalache: enumerar estados o resolver restricciones
Una especificación no se comprueba sola. TLC, el model checker clásico de TLA+, enumera explícitamente valores y estados; Apalache, presentado como el primer model checker simbólico para TLA+, traduce la relación de transición a restricciones SMT sin cuantificadores y delega la búsqueda en un solver. [2]
Ambos comparten un supuesto que conviene tener presente al leer cualquier resultado: todos los parámetros de la especificación están fijados y todos los estados son estructuras finitas. [2] En el ejemplo, eso significa elegir Replicas con cuatro elementos, Byz con uno y Blocks con dos. Si la herramienta no encuentra violaciones, la conclusión es sobre esa instancia. Extenderla a todo requiere una prueba, a mano o con un asistente de demostración, como la que acompaña al paper de HotStuff. [3]
La diferencia práctica entre las dos herramientas está en cómo escalan. La enumeración explícita es directa y produce trazas legibles, pero sufre cuando el espacio de estados crece por combinatoria de mensajes, votos y vistas. Los autores de Apalache reportan que su herramienta supera a TLC en ejemplos con espacios de estados grandes. [2] No es una regla universal para elegir; es un motivo para probar ambas sobre la misma especificación.
Qué compra un equipo al especificar su consenso
Los errores de diseño en consenso BFT aparecen en intercalaciones raras de mensajes y cambios de vista que las pruebas convencionales rara vez ejercitan.
Una especificación TLA+ fija por escrito los supuestos (quórums, equivocación, equidad) y permite buscar contraejemplos de safety en instancias pequeñas antes de tocar la implementación.
Qué aporta frente a Twins y qué no
Twins aborda el mismo miedo desde la implementación. En lugar de una especificación, crea copias gemelas de un nodo con la misma identidad y credenciales, de modo que el resto del sistema ve a un único nodo que se comporta de forma sospechosa; así emula equivocación del líder, doble voto y pérdida de estado interno como los locks. [4] Los escenarios se generan sistemáticamente variando particiones y líderes por ronda, y los autores reportan que su despliegue sobre DiemBFT puede ejecutar 44 millones de escenarios al día. [4]
Los autores son explícitos sobre el contraste: la enumeración exhaustiva de fallas bizantinas en model checking conduce a explosión de estados, y Twins la evita modelando solo ejecuciones correctas, a cambio de cubrir muchos, pero no todos, los ataques bizantinos. La caracterización formal de esa cobertura queda como problema abierto. [4]
De ahí sale una división de trabajo razonable. TLA+ pregunta si el diseño es seguro en todas las ejecuciones de una instancia pequeña, incluidas las que nadie imaginó. Twins pregunta si el código que corre en producción respeta ese diseño frente a escenarios bizantinos generados a escala. Ninguna sustituye a la otra: un modelo verificado no detecta un lockedQC que la implementación olvida persistir, y una batería de escenarios no garantiza que el diseño no tenga una traza mala que ningún generador produjo.
La trampa más común es leer un resultado limpio como "el protocolo está demostrado". Ojo con eso. Un model checker valida la especificación que se le dio, con los parámetros que se fijaron y los supuestos de equidad que se escribieron. Si el modelo omite el cambio de vista, nada dice sobre el cambio de vista.
Checklist mental de Verificación Formal
5 de 5 revisados
Bibliografía académica
- [1]
L. Lamport, "The Temporal Logic of Actions," ACM TOPLAS, vol. 16, no. 3, pp. 872-923, 1994.
Fundamento lógico de TLA+: estados, acciones, invariantes y propiedades temporales.
- [2]
I. Konnov, J. Kukovec, and T.-H. Tran, "TLA+ Model Checking Made Symbolic," Proc. ACM Program. Lang., vol. 3, OOPSLA, 2019.
Model checking simbólico de especificaciones TLA+ (Apalache), aplicado a algoritmos distribuidos tolerantes a fallas.
- [3]
M. Yin, D. Malkhi, M. K. Reiter, G. G. Gueta, and I. Abraham, "HotStuff: BFT Consensus in the Lens of Blockchain," PODC, 2019.
Fuente central para QC, highQC, Chained HotStuff, view-change lineal y three-chain commit.
- [4]
S. Bano et al., "Twins: BFT Systems Made Robust," arXiv:2004.10617, 2020.
Metodología de testing para equivocación, doble voto y fallas bizantinas.
Siguiente lectura
Para ver cómo se generan escenarios bizantinos contra una implementación real, sigue con Twins: detección de errores de estado y bloqueos. Si quieres repasar las propiedades que una especificación de HotStuff debería capturar, vuelve a Safety, liveness y responsiveness en HotStuff.
Rutas vecinas
Si este tema te abrió hambre, sigue por aquí.
Series y labs que comparten área o dependen de esta ruta. Pocas opciones, para no convertir la curiosidad en menú infinito.
Series relacionadas
Ethereum: de historia a labs
Serie progresiva para entender Ethereum desde el whitepaper, forks y The Merge hasta EVM, Solidity, proof-of-stake, rollups, account abstraction, DeFi, observabilidad y laboratorios reproducibles.
Substrate: del runtime al consenso propio
Serie de 20 capítulos, de neófito a experto, sobre Substrate (Polkadot SDK): runtime en Wasm, FRAME, extrinsics, estado, pesos, actualizaciones sin fork, Aura, BABE, GRANDPA, sincronización, parachains, XCM, Sassafras, BEEFY y cómo conectar un consenso BFT propio a un nodo.
Ruta práctica: activos digitales en la operación
Nueve módulos, de menor a mayor dependencia, para decidir cómo usar custodia, wallets, llaves, firmas multifirma y MPC, AML/KYT y stablecoins con Fireblocks, BitGo, Kaleido, Circle y Tether.
Labs para convertir lectura en práctica
Prueba de trabajo y reajuste de dificultad
Laboratorio determinista para medir el costo de la prueba de trabajo y ver cómo el reajuste por altura de bloque estabiliza el tiempo entre bloques.
Consensus benchmark
Banco reproducible para comparar consenso BFT y documentar los trade-offs de HotStuff-2.
Ethereum local: Anvil, wallet y primera transacción
Laboratorio base para levantar una red local, crear cuentas, firmar transacciones y observar receipts sin gastar ETH real.
RPC y Cast: leer Ethereum con lupa
Ejercicios con JSON-RPC y Cast para consultar bloques, nonces, gas, receipts, logs y errores reproducibles.
Sigue leyendo
Ideas conectadas con este artículo
Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.
Ethereum: mapa de lectura antes de tocar Solidity
Ruta completa para aprender Ethereum desde historia y arquitectura hasta EVM, proof-of-stake, L2, seguridad, DeFi y labs reproducibles.
Antes de Ethereum: Bitcoin, scripts y la máquina mundial
Historia inicial de Ethereum: qué problema vio el whitepaper, por qué los contratos generales importaban y qué cambió frente a Bitcoin.
Frontier, Homestead y The DAO: la red aprendió con golpes
De mainnet inicial a The DAO: primeros forks, tensiones sociales y por qué la historia de Ethereum no es solo técnica.
Metropolis a Istanbul: Ethereum madura antes del Merge
Lectura histórica de Byzantium, Constantinople e Istanbul como preparación técnica para una red más segura y escalable.