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

En 1 Minuto

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.

Prerrequisitos
  • Safety, liveness y responsiveness en HotStuff (hotstuff-safety-liveness-responsiveness)
  • Twins: detección de errores de estado y bloqueos (twins-deteccion-errores-estado-bloqueos)
Cuándo Detenerte

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 Rápido de Notación

Glosario de Notación Matemática y Criptográfica

v— Vista (View / Round)

Número de vista o ronda actual. Cada vista tiene un único líder designado.

Ejemplo: view = 42
Haz clic en un símbolo para desplegar su definición formal y su aplicación en el protocolo.
Mapa conceptual

Ruta mental de la Verificación Formal con TLA+

  1. 1. Especificación

    Estados y acciones

  2. 2. Propiedades

    Safety y liveness

  3. 3. Model checking

    TLC o Apalache

  4. 4. Diseño revisado

    Contraejemplo o confianza acotada

Del pseudocódigo del paper a una especificación que una herramienta puede explorar.
Explicación Didáctica

Decodificador Didáctico de Conceptos BFT

Verificación formal con model checking

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.

Traducción de lenguaje formal a analogías intuitivas del mundo real.

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.

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 Init∧□[Next]varsInit \land \Box[Next]_{vars}, más condiciones de equidad cuando se quiere hablar de progreso: "el primer estado satisface InitInit y cada paso es un paso de NextNext o deja varsvars sin cambios".

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.

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.

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.

Texto
---------------------------- 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. 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.

Teorema

Safety de Basic HotStuff (Teorema 2)

Si w y b son nodos en conflicto, no pueden ser confirmados ambos, cada uno por una réplica correcta.
Bosquejo de Demostración: Por contradicción: dos commitQC de la misma vista exigirían que una réplica correcta votara dos veces en la misma fase; para vistas distintas, se toma la primera vista posterior con un prepareQC en conflicto y se muestra que alguna réplica correcta del quórum bloqueado habría tenido que violar su regla de voto.

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 ◊(committed≠∅)\Diamond(committed \neq \emptyset), "en algún momento se confirma algo".

La fórmula □[Next]vars\Box[Next]_{vars} 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 WFvars(Next)WF_{vars}(Next): si una acción queda habilitada de forma continua, termina ejecutándose.

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 vv durante ese periodo y el líder de vv es correcto, se alcanza una decisión. 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.

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. 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 nn requiere una prueba, a mano o con un asistente de demostración, como la que acompaña al paper de HotStuff.

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. No es una regla universal para elegir; es un motivo para probar ambas sobre la misma especificación.

Impacto de Negocio & Finanzas

Qué compra un equipo al especificar su consenso

Problema Comercial / Operacional

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.

Solución del Paper (Insight Técnico)

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.

Impacto para el Producto / Negocio: Revisiones de diseño basadas en trazas concretas y supuestos explícitos, con la advertencia de que el resultado cubre el modelo y la instancia comprobada, no el código desplegado.
SafetyInvariantese comprueba estado a estado
LivenessFórmula temporalrequiere supuestos de equidad
TLCExplícitoenumera estados
ApalacheSimbólicorestricciones SMT

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. 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.

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.

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.

TLA+ Formal Verification

Checklist mental de Verificación Formal

5 de 5 revisados

Preguntas para leer o escribir una especificación de consenso.
Referencias

Bibliografía académica

Formato IEEENumerado para ingeniería, sistemas y protocolos.
  1. [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. [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. [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. [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.

Fuentes primarias, papers seminales y especificaciones técnicas citadas en esta investigación.

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.

Sigue leyendo

Ideas conectadas con este artículo

Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.

Los comentarios se cargan al final de la lectura para no meter peso antes de tiempo.