Artículo de Blog

Por Qué los Quórum Son Importantes y Cómo Stellar los Aborda

Autor

Stellar Development Foundation

Fecha de publicación

Protocolo de consenso Stellar

Prueba de acuerdo

Quorums

Hoy hemos lanzado stellar-core v11.2, una actualización que incluye algunas mejoras cruciales para la configuración y el monitoreo del conjunto de quórum.

La idea básica: como todos los Sistemas de Acuerdo Bizantino Federados, el Protocolo de Consenso Stellar depende de que los validadores elijan buenos conjuntos de quórum para funcionar correctamente. Antes de esta actualización, eso era algo difícil de hacer: los validadores configuraban sus conjuntos de quórum manualmente, y no había una forma fácil de verificar esas configuraciones para ver si creaban la intersección de quórum necesaria.

Para facilitar las cosas a los validadores, hemos diseñado dos soluciones:

  • Configuración automática del quórum
  • Un verificador de intersección de quórum, que implementa un algoritmo desarrollado por Łukasz Lachowski

Estos son cambios importantes, y queríamos informarte qué son, por qué los hicimos y por qué son importantes. Para llegar allí, comencemos con un poco de contexto...

Por Qué la Configuración de Quórum es Importante

Sistemas de Acuerdo Bizantino Tradicionales (BAS)

Un sistema distribuido sistema compuesto por nodos individuales nodos requiere un mecanismo que permita a esos nodos alcanzar acuerdo. El Acuerdo Bizantino es uno de esos mecanismos.

BAS puede tolerar cierto número f de nodos bizantinos. En la práctica, para que el sistema tolere f nodos defectuosos, debe tener al menos 2f +1 nodos honestos, o 3f + 1 nodos en total.

Ilustremos esto con el clásico Problema de los Generales Bizantinos. Frente a un ejército opuesto, un general y sus tenientes deben acordar si atacar o retirarse. Sin embargo, cualquier teniente (o incluso un general) puede ser un traidor. Un general envía órdenes de atacar o retirarse a sus tenientes de tal manera que (1) todos los tenientes leales obedezcan sus órdenes, y (2) si el general es leal, entonces cada teniente leal obedece la orden del general.

Considera el caso de un general y dos tenientes. Supongamos que uno de los tenientes (A) es un traidor: recibe una orden de atacar, pero le dice a otro teniente que se retire. El otro teniente (B) recibe órdenes contradictorias (atacar del general, y retirarse del teniente A), y no tiene forma de verificar quién es leal y quién es traidor.

Por otro lado, supongamos que ambos tenientes son leales, pero el general es un traidor, y envía una orden de atacar al teniente A y retirarse al teniente B. El teniente leal A envía “atacar” al teniente B, pero el teniente B recibió “retirarse” del general, y por lo tanto, no puede proceder. Este sistema no puede tolerar un solo traidor para tomar una decisión.

Ahora agreguemos otro teniente (C). Supongamos que el mismo teniente malicioso A mencionado anteriormente recibió nuevamente una orden de ataque, pero le dice al teniente B que se retire. El teniente B recibe dos órdenes de atacar (del general y de C), y una orden defectuosa de retirarse. El teniente B ahora puede identificar a un traidor y ejecutar la orden correcta. Tal sistema tolera un fallo.

Acuerdo Bizantino Federado

En BAS, simplemente asumimos que necesitamos el acuerdo de más de dos tercios del todo sistema. Cada participante es igualmente confiable. Pero considera el mundo real: ¿qué pasa si tienes una red de nodos que representan diferentes organizaciones: bancos, organizaciones sin fines de lucro, proveedores de remesas, comerciantes de café, etc.? No necesariamente te importa si el comerciante de café es bizantino. ¿Y si solo quieres confiar y depender de un grupo más pequeño de nodos para lograr el consenso?

Esto es exactamente lo que un sistema FBA te permite hacer: te permite configurar tu propio trozo de quórum para decirle al mundo en quién confías.

La ventaja de la confianza flexible que un FBA proporciona es que hace las cosas más difíciles para un actor malicioso para hacer cosas malas: incluso si agrega un millón de nodos malvados a la red, no tendrán ningún efecto a menos que convenza a una masa crítica de nodos para incluirlos en sus trozos de quórum. Tendría que convencer a muchas personas para confiar en muchos nodos. Por otro lado, un sistema BA tradicional estaría comprometido, ya que cada nodo confía en todos los demás nodos de la red.

Vale la pena señalar que un sistema BA es en realidad un sistema FBA también! En BA, cada nodo tiene la misma configuración, donde cada conjunto de más de dos tercios del sistema entero es un trozo de quórum, por lo que es redundante configurar explícitamente trozos de quórum. Por otro lado, FBA generaliza BA, permitiendo que un nodo elija sus propios trozos.

Por Qué la Configuración de Quórum es Difícil

Con gran poder viene una gran responsabilidad. La flexibilidad de las configuraciones de quórum definidas por el usuario permite una membresía de red verdaderamente abierta (cualquiera puede unirse) y un control descentralizado (ninguna autoridad central dicta cuyo voto se requiere para el consenso). Sin embargo, la libertad para configurar tus propios trozos de quórum puede resultar en configuraciones de red inválidas tales que:

  • Partes de la red pueden depender de nodos no confiables (no disponibles), facilitando detener el progreso del consenso. La red se detiene.
  • Partes de la red podrían no saber sobre cada uno, produciendo diferentes resultados de consenso. La red se bifurca.

Para prevenir paradas y bifurcaciones, una configuración de red necesita equilibrar propiedades de vitalidad y seguridad.

La vitalidad depende de la fiabilidad de los nodos en un quórum: si demasiados nodos se caen, un quórum deja de progresar. La seguridad se basa en intersección de quórum: si los conjuntos de quórum no se superponen, los nodos terminan con diferentes resultados de consenso.

El diagrama a continuación muestra dos configuraciones diferentes que afectan la intersección de quórum (asume que G no es bizantino).

Una red que no disfruta de intersección de quórum (Los nodos ABC son independientes de DEFG)
Tan pronto como A agrega a G en su trozo de quórum, se logra la intersección de quórum.

Nota que mientras la intersección de quórum es necesaria para la seguridad, no es suficiente para garantizar la seguridad: si el nodo G se vuelve bizantino y decide dejar de enviar mensajes, la red aún puede bifurcarse.

No Siempre Puedes Obtener lo que Quieres

The Rolling Stones probablemente no se referían a sistemas distribuidos, pero resumieron el problema de manera agradable. Es imposible lograr tanto la seguridad como la vitalidad en un sistema propenso a particiones de red (si no eres ajeno a los sistemas distribuidos, podrías reconocer que el teorema CAP es un ejemplo de este hecho fundamental).

Aunque en el contexto de los sistemas FBA la vitalidad varía entre quórum (algunos quórum pueden progresar, mientras que otros se detienen debido a nodos no confiables), todavía hay un compromiso entre seguridad y vitalidad, influenciado por la configuración general del quórum.

Para ilustrar esto, considera una red configurada con dos quórums (cada uno capaz de tolerar un fallo) que se superponen por un solo nodo. Si ese nodo se vuelve no disponible, ambos quórums pueden acordar diferentes valores, poniendo en peligro la seguridad (pero ambos sosteniendo la vitalidad). Por otro lado, supongamos que dos quórums están configurados para superponerse por el 50% de los nodos. Si esos nodos superpuestos se comportan de manera no confiable, ambos quórums podrían perder vitalidad, priorizando la seguridad.

Cómo Facilitamos la Configuración de Quórum

Imagina intentar tener todo eso en mente mientras configuras un validador de la red Stellar y construyes manualmente un conjunto de quórum. Quieres equilibrar la seguridad y la vitalidad y tomar decisiones que aseguren la intersección de quórum, pero es fácil cometer errores y es difícil mantener una vigilancia constante sobre los nodos en tu conjunto de quórum. Si calculas mal los umbrales para las rebanadas de quórum de tu nodo, lo cual es fácil de hacer, pones en riesgo la intersección de quórum y, por lo tanto, la seguridad de la red. Si confías en demasiados nodos poco fiables, puedes obstaculizar la vitalidad y evitar que la red progrese. Nos damos cuenta de que la configuración de quórum es difícil, por eso hemos comenzado a ingeniar soluciones para facilitarlo.

Configuración Automática de Quórum

Como primer paso hacia la simplificación y mayor intuición de la configuración de quórum, estamos automatizando parte del proceso. Ahora, stellar-core agrupa validadores dirigidos por la misma organización, construye una jerarquía basada en la calidad del validador y establece umbrales basados en las mejores prácticas. Así es cómo funciona:

Agrupación de Validadores

La redundancia dentro de una organización en la red Stellar es una buena práctica, por lo que recomendamos ejecutar al menos tres validadores para una alta disponibilidad. Anteriormente, stellar-core no distinguía entre validadores y organizaciones, dejando al usuario la responsabilidad de configurar las rebanadas y umbrales correctamente. Considera un ejemplo simple de configuración de rebanada de quórum:

{A, B, C, D, E, F, G} — umbral 67%

Parece razonable. Hay siete nodos, y se necesitan cinco para acordar y alcanzar el consenso. Sin embargo, ¿qué pasa si en lugar de nombres de nodos, simplemente indicamos el nombre de la organización que los opera?

{SDF1, SDF2, SDF3, SDF4, SDF5, LOBSTR, SATOSHIPAY} — umbral 67%

El problema es más visible ahora. Si LOBSTR y SATOSHIPAY no están de acuerdo con lo que dice SDF, SDF procederá de todos modos, ya que sus propios nodos están de acuerdo, cumpliendo con el umbral.

El problema aquí es que las organizaciones no están ponderadas correctamente porque algunas de ellas operan más nodos que otras. Desde el punto de vista del consenso, nos importa una organización como un todo, no sus validadores individuales.

Para reflejar esa preocupación, stellar-core ahora te permite especificar HOMEDOMAIN para cada validador. Los nodos operados por una organización tienen el mismo dominio y se agrupan automáticamente con un umbral de mayoría simple (51%). Si HOMEDOMAIN se especifica correctamente para cada nodo, la configuración anterior se convierte automáticamente en:

{{SDF1, SDF2, SDF3, SDF4, SDF5 — umbral 51%}, LOBSTR, SATOSHIPAY} — umbral 67%

Calidad del Validador

Los validadores ahora especifican la calidad de los nodos en sus rebanadas de quórum. La calidad es algo subjetiva, pero el sistema de calificación funciona mejor si sigues las pautas y usas el sentido común al asignar valores.

Hay tres categorías: ALTA, MEDIA, BAJA. Un validador de alta calidad es fiable (parte de una organización que ejecuta al menos tres validadores), publica un archivo de historial y tiene un historial de buen comportamiento en la red.

Un validador de calidad media podría ser menos fiable o menos conocido por la red. Es candidato a convertirse en un validador de alta calidad si sigue siendo fiable, comienza a publicar un archivo y gana el respeto de la red principal.

Un validador de baja calidad aún no es conocido ni confiable por la red. Si demuestra ser fiable y digno de confianza con el tiempo, puede ser promovido a una calidad superior.

El siguiente diagrama muestra cómo se agrupan los nodos después de que especificas una calificación de calidad para cada nodo en tu rebanada de quórum:

Estructurar los nodos de esta manera ayuda a la vitalidad, ya que los nodos de alta calidad son más propensos a estar disponibles (debido a requisitos de fiabilidad más estrictos). En caso de que un nodo de alta calidad sea bizantino o se caiga, el grupo de calidad media actúa como respaldo para asegurar el consenso. En otras palabras, el acuerdo entre todos los validadores de calidad media equivale a un voto en el nivel de alta calidad. De manera similar, el acuerdo entre todos los validadores de baja calidad equivale a un voto en el nivel de calidad media.

Verificación de Intersección de Quórum

Recuerda que la intersección de quórum es esencial para la seguridad de la red. El monitoreo continuo de quórum es una parte crucial de la identificación de malas configuraciones. Resulta, sin embargo, que identificar la falta de intersección de quórum es difícil. De hecho, es un problema NP-completo: una solución no se puede encontrar de manera eficiente (en tiempo polinomial), pero una solución dada se puede verificar eficientemente. Es difícil, porque para una red de N nodos, debemos iterar a través de 2ᴺ subconjuntos posibles y verificar la ausencia de intersección de quórum.

A pesar de esa dificultad, Stellar-core v11.2 ofrece un mecanismo para verificar la intersección de quórum de manera relativamente rápida reconociendo que algunos subconjuntos en realidad no necesitan ser verificados. Al explorar todos los conjuntos en un orden particular, dejamos de verificar conjuntos innecesarios lo antes posible. Para más información sobre el algoritmo, consulta este documento: https://arxiv.org/abs/1902.06493

La función se habilita a través de la nueva configuración QUORUM_INTERSECTION_CHECKER, y se activa en segundo plano cuando el conjunto de quórum de un nodo cambia. Si no se encuentra la intersección de quórum, se emite una advertencia, y la información sobre la división se añade a la salida del info endpoint.

El Futuro Es Emocionante

Estamos comprometidos con nuestra misión de promover la inclusión financiera global. Creemos que los desafíos que tenemos enfrente requieren un enfoque metódico e incremental. Los cambios que estamos introduciendo en esta versión son el primer paso hacia quórum más seguros y fuertes, ¡y no podríamos estar más emocionados de continuar mejorando la experiencia en Stellar!

Puedes leer las notas completas de la versión aquí.