You are on page 1of 12

El problema de los generales bizantinos

La tecnología blockchain, también conocida como “contabilidad distribuida” (o con sus siglas
inglesas DLT) o en castellano “cadenas de bloques”, es un protocolo de operaciones de intercambio entre
pares que se producen, gestionan y comprueban de forma descentralizada, automatizada, compartida y
segura. Pero en la base para que la tecnología blockchain sea fiable está el consenso.
¿Qué es eso del consenso? Pues que todos los integrantes de una red están de acuerdo en que
una transacción X ha ocurrido entre dos miembros de la red en un momento temporal
determinado. Simplemente. Para ponerse de acuerdo, evitando engaños y minimizando errores, es
cuando se pone en práctica la solución al problema de los generales bizantinos.

El problema de los generales bizantinos es un viejo juego de lógica: en un asedio hay un número
indeterminado de generales que debe coordinarse para la conquista. Sólo uno cursa la orden (que es
binaria, atacar o retirarse), el comandante, el resto son tenientes. Puede haber uno o más traidores
(comandante incluido), con el objetivo de que no se cumpla la orden.

Todos a una, pero vigilándose


Así, y simplificando mucho, cada teniente (miembro de la red) recibe una orden (transacción) y
emite la misma a los demás. La orden contradictoria del traidor quedaría en minoría, incluso si es el
comandante (el que ordena la transacción), y se dará por verdadera la orden mayoritaria. Los
traidores maliciosos son así neutralizados.
Existen ciertas condiciones que las blockchain reales crean para hacer más resistente el consenso
obtenido a través de este sistema de prueba de trabajo (POW en inglés), que es como se le suele
llamar:
 Todos los generales se comunican con todos los demás.
 Todo general sabe quién le envía la orden.
 Ante una ausencia de mensaje hay una orden por defecto.
 Las órdenes están escritas y firmadas.
 Los errores aleatorios se controlan mediante códigos de detección de errores.
 El sellado temporal confiable evita la duplicación de órdenes.
La resolución de este dilema, alcanzada en 1982, es una de las bases fundamentales del
funcionamiento de las cadenas de bloques, y el elemento que hace que sean una forma fiable de hacer
transacciones entre nodos no necesariamente fiables: todos los nodos participan y registran todas las
transacciones. Los cimientos del futuro están planteados
El problema de los generales bizantinos
Sitúese.
Está usted en el campo de batalla arrasado, y el viento ondea sus banderas blasonadas, que amenazan
la ciudad rebelde, por fin sitiada. Sin embargo, las torturas a las que ha sometido a los infieles no han minado
el espíritu enemigo y ningún prisionero ha revelado la cantidad de hombres que guarda la ciudad amurallada.
Usted tiene un ejército numeroso, sí, pero las líneas de comunicación y aprovisionamiento han sido
destruidas: no podrá mantener demasiado el sitio sobre la ciudad. Urge tomar una decisión sobre el curso de
la batalla y, como general que es, deberá consultar con el resto de mandos. Las opciones son pocas: atacar
todos a la vez o retirarse.
Pero hay un gran problema: sospecha usted que el enemigo se ha infiltrado en sus filas hasta tal punto
que es posible que algunos de sus compañeros generales se encuentren, secretamente, sirviendo al enemigo.
¡Hay traidores entre los generales! Usted sospecha de un par de ellos, pero sólo si es capaz de ponerse de
acuerdo con otros generales leales en su acusación podrá desenmascarar a los traidores. No puede usted pensar
mucho, sus hombres son bravos pero la lealtad se resiente con el estómago vacío. Sólo podrá derrotar al
enemigo si ataca con todas las fuerzas de los generales leales así que... ¿podrá usted descubrir a los traidores?
¿Será capaz usted de poner de acuerdo a los generales bizantinos?
El problema de los generales bizantinos fue formulado de esta forma (con menos literatura) por Leslie
Lamport1,2, uno de los grandes de la informática, en 1982. Desde entonces es uno de los clásicos en la teoría
de sistemas distribuidos. ¿Y por qué? Pues veamos.
Piense que en vez de tener usted un conjunto de generales bizantinos tiene usted un conjunto de
computadores distribuidos, llevando a cabo una tarea común. Por ejemplo, una transacción bancaria o la
monitorización de la ruta de un avión. Eso suena más informático.
Supongamos que uno de los computadores del sistema deja de funcionar. Hace plof y ya está. No responde a
los mensajes del resto, ni ofrece resultados: nada. ¿Como podemos saber que ha fallado? Pues muy fácil,
como no hace nada ni envía los mensajes que tiene que enviar ni responde a las llamadas, deducimos que ha
fallado. Lo más sencillo entonces es reemplazarlo: que otro haga la misma tarea que realizaba. Si un
componente 'se muere' de este modo, decimos que ha fallado en modo crash.
Ahora el mismo componente falla, pero en vez de no hacer nada siempre realiza su tarea más tarde de
lo que debería. ¿Cómo nos damos cuenta de este fallo? Pues tan sólo nos es necesario poner en marcha un
reloj cuando debería iniciarse. Si, transcurrido el tiempo determinado, el computador o componente no ha
ofrecido un resultado, sabemos que está fallando. Y podemos reemplazarlo por otro, como antes. En este caso
decimos que el componente falla en modo performance.
Un pasito más. Supongamos que un elemento ofrece resultados dentro del tiempo establecido, pero...
estos resultados son siempre incorrectos. Aquí se complica la cosa. ¿Cómo sabemos si falla? Podemos, por
ejemplo, poner dos procesadores a hacer la misma tarea y comparar los resultados, pero aun así si estos no
concuerdan, ¿cómo saber cuáles son los buenos y cuáles no? En este caso necesitamos tres componentes para
tolerar el fallo de uno. Y, en general, 2n+1 para tolerar n fallos. Estos fallos se llaman response. Y los sistemas
con tres componentes y un comparador se llaman TMR (triple modular redundancy).
¿Se han fijado cómo cada vez necesitamos más cosas para detectar el fallo?
Y ahora vamos a lo bueno. Supongamos que un componente tiene un comportamiento errático y que,
a veces ofrece una respuesta correcta y a veces no. Supongamos que, en las votaciones para detectar la
respuesta correcta, este computador acusa a otros de ser los erróneos: a uno le dice una cosa, a otro otra
distinta. Actúa como un traidor. Como un traidor bizantino.
Está usted de nuevo en el campo de batalla. Y ya tiene su decisión, atacar o retirarse, que debe transmitir
al resto de generales. Los generales leales no se equivocarán, y si creen que atacar es la mejor opción,
arrasarán al enemigo. Sin embargo, puede que los traidores consigan que decidamos retirarnos. Por otro lado,
aunque una mayoría de generales leales haya decidido no atacar, es posible que con el voto de los traidores
se fuerce el asalto, cayendo en una trampa mortal.
Usted razona: si sólo hubiera tres generales y uno fuera el traidor... ¿podríamos ponernos de acuerdo la
mayoría? Supongamos que yo -Apocapes- envío a ambos la orden de atacar. Los generales Belisarius y
Comentiolus reciben mi orden, bien. Y, sin embargo, el traidor Belisarius informa a Comentiolus de que mi
orden ha sido la de retirada. ¿Qué pensará Comentiolus? Pues que, o bien Belisarius es el traidor, como de
hecho sucede... ¡o bien que el traidor soy yo, el insigne general Apocapes!. Las dos situaciones serían
indistinguibles a los ojos de Comentiolus.
Así que, a pesar de ser mayoría los generales leales (de 2 a 1), no podremos llegar nunca a un acuerdo,
pues no sabremos de quien fiarnos. Si dispusiéramos de cartas firmadas... podría enviar cada una de ellas al
resto de generales y luego estos intercambiar las mismas. Sin embargo, cada general sólo puede controlar lo
que transmite, no lo que intercambia el resto.
Entonces ¿y si somos cuatro y uno infiel? Entonces sí que será posible, puesto que Droctulf, el cuarto
general, podrá confirmar que yo di la orden de atacar. ¿Será posible que con más del triple de generales leales
podamos acordar una solución?
Por supuesto, la suposición a usted no le vale. Necesita la prueba matemática de cuántos generales son
necesarios para llegar a un acuerdo con t generales traidores infiltrados. Pero eso aquí no aparecerá: digamos
que simplemente imagina grupos de 3t o menos generales generales (albaneses) que alcanzan el acuerdo:
consigue reducir el problema al de los tres generales encontrando por tanto una contradicción. Se requieren
3t + 1 generales leales para acordar una solución.
Las banderas se hinchen con renovada fuerza en el campamento. Los generales que rodean la ciudad
son 8 y, si el Imperio Bizantino aún conserva parte de su gloria, los traidores serán dos de ellos. Ahora sabe
usted que sin duda podrán alcanzar la mejor decisión.
¿Y qué tiene que ver esto con la informática? Pues mucho. Si usted no es capaz de evitar los fallos
bizantinos en sus programas o componentes que actúan de manera distribuida, sepa que cualquier sistema de
decisión requerirá de al menos MAS DEL TRIPLE de componentes que actúen correctamente que los que
no3.
Y eso es vital en Tolerancia a Fallos: los sistemas están diseñados para que cualquier tipo de fallo
pueda convertirse en uno tipo crash. Aunque se necesite aumentar la circuitería o software de detección, los
fallos crash (u omission) -semántica débil de fallo- son por lo general más fáciles de tratar.
Y por eso se le suele dar muerte a los traidores. Es la solución más ingenieril.
1
el problema de los generales es más antiguo, pero la generalización de Lamport es la más conocida.
2
¿Sabían que Leslie Lamport también creó LaTeX (Lamport TeX)?
3
siempre que las comunicaciones sean como las descritas, esto es, que un miembro no puede garantizar
que e estado que de él transmiten los otros es cierto.

LESLIE LAMPORT, ROBERT SHOSTAK, and MARSHALL PEASE. The Byzantine Generals Problem. ACM
Transactions on Programming Languages and Systems, Vol. 4, No. 3, July 1982, pp 382-401.
Problema de los generales bizantinos
El problema de los generales bizantinos es un experimento mental para plantear, de una forma
metafórica, el problema que se da entre un conjunto de sistemas informáticos que tienen un objetivo
común. Deben encontrar un plan de acción común a partir de una estructura jerárquica, donde uno de los
sistemas que tiene mayor rango proporciona una orden a partir de la cual el resto de sistemas tiene que
operar (fijar su decisión). Además es posible que alguno de ellos no sea fiable y provea información falsa
de forma intencionada.12

Planteamiento del problema


Supongamos un escenario de guerra en el que tenemos un grupo de m generales bizantinos que
están asediando una ciudad desde distintos lugares y tienen que ponerse de acuerdo para atacar o retirarse
de forma coordinada. Entre los generales hay solo uno que puede cursar la orden por ser el comandante.
El resto se dice que son tenientes.
Los generales se comunican a través de mensajeros y las dos posibles órdenes del comandante son
"atacar" y "retirarse".
Uno o más de los generales puede ser un traidor (al resto se les llama leales), por lo que su objetivo
es conseguir que todos los generales leales no se pongan de acuerdo. Para ello pueden ofrecer
información errónea. Por ejemplo, si el comandante es el traidor, podría mandar órdenes contradictorias
a los distintos tenientes. Si el teniente es un traidor podría indicarles a otros tenientes, con el fin de
confundirlos y que creyeran que el traidor es el comandante, que el comandante les envió la orden
contraria a la que realmente les envió.
Para resolver el problema tenemos que buscar algoritmos que nos permitan conseguir alguno de
los siguiente objetivos:3
 Todos los tenientes leales toman la misma decisión.
 Si el comandante es leal, entonces todos los tenientes leales realizan la orden que él
decidió.
Normalmente para llegar a una solución se suelen hacer las siguientes condiciones adicionales:32
 Cada mensaje que se envía llega correctamente.
 Cada receptor de un mensaje conoce quién lo envía.
 La ausencia de mensaje puede ser detectada.
 Ante la ausencia de mensaje se tiene una orden por defecto. Esta condición es para evitar
el problema de que el comandante sea un traidor y no envíe órdenes.
Algoritmos solución
En 1982 Leslie Lamport, Robert Shostak y Marshall Pease4 proporcionaron distintos algoritmos de
solución en función de condiciones adicionales.
Mensajes orales y todos se pueden comunicar con todos
La estrategia se basa, con el fin de detectar si el comandante es el traidor, en que los tenientes se
reenvíen entre sí la información que el comandante les ha mandado. Si el teniente es leal la información
que transmitirá el teniente será la que le envió el comandante. La consecuencia de usar mensajes orales
(no firmados) es que un general traidor puede decir que el comandante le ha mandado cierta información
cuando no es así.
Caso de 3 generales
Analicemos el caso en el que tenemos tres generales (m=3).
 Supongamos que el comandante es un traidor. Si el comandante envía una orden distinta
a cada teniente entonces habrá un teniente que no sepa qué acción realizar:

Problema de los 3 generales bizantinos con comandante traidor


 Supongamos que un teniente es el traidor. Entonces este retransmite al otro teniente
información distinta a la que recibió del comandante. Por tanto, el otro teniente no sabrá qué
acción realizar:

Problema de los 3 generales bizantinos con teniente traidor


La conclusión es que no existe solución que garantice que se cumplan las condiciones del problema
si se permite que con tres generales uno sea un traidor. Esto es debido a que no hay suficientes generales
para formar una opinión consensuada.
Caso de 4 generales
Si tuviéramos 4 generales (m=4) sí sería posible el acuerdo a través del siguiente algoritmo:
Al recibir la orden del comandante y los mensajes de los otros 2 tenientes, los tenientes
leales decidirán la orden de consenso según la siguiente función de mayoría:

Devolver el valor de v que sea mayoría entre .

Donde el valor de es la orden mandada desde los distintos generales al general al que
estamos evaluando su decisión.
Veamos el esquema si el comandante es leal y un teniente es traidor:

Problema de los 4 generales bizantinos con teniente traidor


Veamos el esquema si el comandante es traidor y los tenientes leales:

Problema de los 4 generales bizantinos con comandante traidor


Caso de m generales
Generalizando a m generales se puede decir que si tenemos t traidores necesitamos que m sea al
menos 3t+1. Al algoritmo generalizado se le llama OM(m) (donde las siglas OM vienen del inglés Oral
Messages) y viene descrito por usar la siguiente función de mayoría:

Devolver el valor de v que sea mayoría entre

Donde el valor de es la orden mandada desde los distintos generales al general al que
estamos evaluando su decisión.
Mensajes firmados y todos se pueden comunicar con todos
En este escenario los mensajes van firmados (se trata de mensajes escritos). Al ir firmados no son
modificables y por tanto los traidores no pueden modificarlos y decir que provienen del comandante. En
esta situación es posible resolver el problema con sólo tres generales y uno de ellos traidor. El algoritmo
de este tipo de problemas se llama SM(m) (donde SM viene del inglés Signed Messages) y es el siguiente:
Primero el comandante envía una orden firmada a todos los tenientes. Cada vez que un
teniente recibe un mensaje firmado lo guarda, hace una copia, la firma y la reenvía a todos los
tenientes que no venían en la firma del documento. Según este algoritmo los generales no
recibirán más mensajes cuando tengan todas las posibles combinaciones. Una vez recibidas, cada
nodo toma la decisión basándose en la orden transmitida por la mayoría.
En este escenario los comandantes traidores son descubiertos inmediatamente ya que han firmado
órdenes contradictorias.
No todos se pueden comunicar con todos
Si falta alguno de los caminos de comunicación las cosas se complican. Veamos los requerimientos
tanto cuando hay mensajes orales como mensajes firmados.
 Con mensaje orales el algoritmo OM(m) solo funciona bajo la condición de que el grafo
de caminos posibles entre generales sea 3m-regular (cada nodo tiene al menos 3m vecinos), lo
que implica 3m+1 nodos (generales). A esta versión del algoritmo se le llama OM(m,p), donde p
es el número de vecinos.
 Para mensajes firmados la única condición es que todos los generales leales estén
conectados, para que así los traidores no puedan bloquearle y evitar que le pasen o pase la orden
firmada.
Consideraciones
 El problema de los dos generales bizantinos es el mismo que se tiene cuando se realiza
una transmisión de dinero sin un intermediario confiable.1 Bitcoin ofreció la primera solución
práctica a este problema.
 En el mundo real las líneas fallan de forma no deliberada. Para detectarlas se pueden usar
códigos de detección de errores. En un escenario con mensajes orales, una línea que falla puede
considerarse como un nodo traidor. Si se utilizan mensajes firmados entonces un fallo en una
línea se detectaría de forma irrefutable.
 Para reconocer al emisor de un mensaje empleando mensajes orales, se deberían tener
líneas fijas y no redes de comunicaciones. Con mensajes firmados no hay problema para
reconocer al emisor.
 La ausencia de mensajes se suele detectar usando time-out (límites de tiempo).
 En el mundo real nunca está garantizado que un error aleatorio no pueda falsear una firma.

Sin embargo esto tiene una probabilidad muy baja con métodos de firma adecuados.
 Evitar fraudes deliberados se convierte en un problema criptográfico. Por tanto, es
importante elegir algoritmos de firma seguros.
 Se debe detectar si un mensaje se envía dos veces, mediante la comprobación de su firma.

De tal modo que una firma no puede ser generada si el proceso ya ha visto esa misma firma en
otro instante.

Referencias
 Bitcoins y el problema de los generales bizantinos. Cristina Pérez-Solà y Jordi Herrera-
Joancomart. Universitat Autònoma de Barcelona. 2014
  Tarea 2. Sistemas Distribuidos. Marcelo Valdivia Lagos. 04/04/2013
  The Byzantine Generals Problem. Manuela Lütolf
 The Byzantine Generals Problem. Leslie Lamport, Robert Shostak y Marshall Pease.SRI
International 1982
La prueba de trabajo es la única solución al problema de los
generales bizantinos

Imagina que estás sentado en un bunker. No tienes ni idea de la gente que hay fuera ni de cuáles
son sus intenciones. Tú sólo recibes mensajes entrantes de desconocidos que pueden contener cualquier
cosa. Pueden ser basura aleatoria o ser mensajes preparados para confundirte. No puedes saberlo ni
puedes confiar en nadie.
El problema del dinero o de cualquier otro “contrato social” es que todo el mundo debe ser capaz
de saber lo que la mayoría acuerda sin necesidad de confiar en un intermediario (o de otra forma estos
podrían abusar de su posición ventajosa). Si todo el mundo vota por “X”, entonces tú sentado en tu
bunker debes llegar a saber de alguna forma que la gente fuera ha votado “X” y no “Y” o “Z”. Pero
recuerda: no puedes confiar en los mensajes de nadie, y mensajes es lo único que recibes del mundo
exterior.
Cuando dos propuestas llegan a tu bunker, “X” e “Y”, no tienes referencia válida para saber cuál
de las dos es la mayoritariamente votada. Sólo tienes los datos mismos que te llegan para juzgar cuál de
las opciones elegir. Para hacer las cosas más sencillas, no estamos intentando aplicar un juicio subjetivo
a cada una de las opciones, sino hacer que todo el mundo converja en elegir una de ellas. En el caso del
Bitcoin es una asunción razonable pensar que cada uno es propietario de su dinero, y que por lo tanto a
nadie le importa mucho cuál es la versión de la historia siempre y cuando su propio balance sea
respetado.
Así pues ¿cómo de diferente debería ser “¿X” de “¿Y” para saber que nadie accidentalmente podría
escoger “¿Y”, “Z” o “W”? Primera propiedad: estos datos deben ser recientes. De esa forma sabemos
que no estamos sentados sobre algún viejo acuerdo mientras todo el mundo se ha mudado a otro más
reciente. Segunda propiedad: cualquiera alternativa “reciente” debe ser imposible de producir. Si es
posible que sea producida, siempre existe la posibilidad de que un determinado número de personas
hubiera optado por ella como alternativa. Y no tienes forma de saber cuántas alternativas existen y
cuántas personas las han adoptado (porque sigues sentado en un bunker y no puedes confiar en los
mensajes entrantes ni saber qué otros mensajes te estás perdiendo).
Problema de los generales bizantinos
¿Como definimos imposible? Significa dos cosas: o es lógicamente imposible, o es prácticamente
(económicamente) imposible. Si es lógicamente imposible, entonces podemos conocer todos los futuros
acuerdos de forma anticipada (como una secuencia determinada de números), simplemente usando la
inducción. Pero esto no funciona así porque tendríamos que haber llegado a alguna clase de acuerdo
sobre un punto de partida en primer lugar. Así que terminamos con la imposibilidad práctica. En otras
palabras, lo que necesitamos es lo siguiente:
El mensaje “X” debe ser reciente de forma probada y las alternativas han de ser
prácticamente imposibles de producir.
La imposibilidad práctica puede ser redefinida en términos de “coste de oportunidad”: hay un
número limitado de recursos físicos y si estos han sido asignados mayormente a X antes que a Y
deberíamos podemos ver que X ha chupado para sí mismo todos los recursos de todas las demás
alternativas. Porque de lo contrario, habría una gran incertidumbre en cuanto al uso de los recursos
remanentes: ¿pueden haber ido a parar a Y? ¿Es posible que X no chupara todos los recursos y que aún
así las alternativas no resulten posibles? Eso implicaría que X se sigue lógicamente de cualquiera sea el
estado previo en el sistema y que por lo tanto no es necesario un proceso de votación.
Por lo tanto: el mensaje X debe ser reciente de forma probada y debe haber gastado –de forma
probada también– una gran cantidad de recursos, suficientemente grande como para que no haya
recursos para producir otras alternativas en un periodo corto de tiempo. Además, el mensaje X
debe ser siempre reciente y debe siempre superar cualquier alternativa. Porque no podemos fiarnos de
los mensajes recibidos anteriormente: ¿y si “Y” es un mensaje antiguo que ha llegado ahora o que ha
sido producido tras X cuando hubo recursos disponibles?
Esto lógicamente nos lleva a lo siguiente: debemos aceptar sólo los mensajes con la mayor prueba-
de-trabajo asociada a ellos, y esa prueba-de-trabajo debe ser tan grande como sea posible, de manera que
no haya posibilidad de que una alternativa pudiera ser producida en ese corto lapso de tiempo. Y esa
prueba-de-trabajo debe ser constantemente reforzada o el valor del consenso previo empezará a
desvanecerse rápidamente según crece la oportunidad para otras alternativas.
Las granjas caras y altamente especializadas son la forma más fiable de llegar a un consenso.
Si fuéramos a usar recursos no especializados, sería complicado que valorásemos si la mayoría de ellos
están siendo en realidad usados para prueba-de-trabajo. Mediante la observación de esa enorme cantidad
de trabajo aplicada a una parte muy específica y fácil de observar de la economía, podemos estimar cuán
caro es producir un mensaje alternativo con el mismo grado de dificultad asociado. En el caso de las
granjas de minado de Bitcoin, una alternativa requeriría una cadena de producción muy cara y compleja
como para superar a otras firmas que producen chips, o bien se vería forzada a construir data-centers de
uso único en los lugares con mejor ratio de costo/efectividad del planeta (con la electricidad más barata,
el clima más frío, baja latencia en la conexión, etc.).
Conclusión
Si alcanzar un consenso de una forma que no implique la confianza es posible en la práctica, sólo
lo es con un esquema de prueba-de-trabajo y cadenas de producción caras y altamente especializadas.
Además, el consenso es solamente válido durante un corto periodo de tiempo, así que debe ser
constantemente reforzado.

You might also like