This module introduces Byzantine consensus algorithms in which agents reach consensus in a sequence of synchronized rounds even though some agents don't follow the protocol.
In this module we study algorithms by which a collection of agents reach a consensus among alternative values. The Paxos algorithm is an example of how agents reach consensus. Agents cannot reach consensus if message delays or agent operations are arbitrarily slow. Next, we study a consensus algorithm in which message delays are bounded and in which agents are guaranteed to come to a consensus even though some agents do not follow the protocol.The algorithm operates in a sequence of steps called rounds. All messages sent in a round are delivered in the next round. Agents execute actions in each round after receiving messages sent in the previous round; these actions may include sending messages. So, the Byzantine algorithm is synchronous.
The figure below illustrates the difference between loyal and disloyal generals.
A loyal general sends attack messages to all lieutenants or sends retreat messages to all lieutenants. A disloyal general sends arbitrary messages to lieutenants.
The specification does not require that traitors be discovered. For example, the algorithm doesn't have to determine whether the general or a lieutenant is loyal or disloyal.
If the only requirement is validity, and consensus isn't required, then the solution is trivial: all loyal lieutenants obey the general whether the general is loyal or disloyal. If the only requirement is consensus then the solution is trivial: all loyal lieutenants agree on a predefined value, say retreat, regardless of the command issued by the general. The conjunction of both requirements makes the problem difficult.
A reliable lieutenant who does not get a message from in round 0 treats the absence of the message as the same as receiving a retreat message. Likewise, if a loyal lieutenant gets a message that is not an attack or a retreat message then the lieutenant treats the message as a retreat message. (We use retreat as a default. We could just as well have used attack as the default.)
Next, we give an overview of the algorithm.
Local Variables
Associated with each lieutenantC
are local variables
C.received
and C.sent
which are sets of
agents (general or lieutenants).
C.received
is the set of agents from which
C
has received attack messages (or their copies).
C
sends attack messages (or copies) from agents in
C.sent
.
The symbol g
represents the general.
A.sent = {}
for all lieutenants
A
.
A
:
A.received = {g}
A
:
A.received = {}
A.received = {g}
for some lieutenants A
,
and A.received = {}
for the others.
r
stepping from 1 to t+1
. The
r
-th iteration for loyal agent c
consists of
the following two steps.
r > 0
Step 1
if (|C.received| >= r) AND (g in C.received): C.commit = True C.sent = C.received UNION {C}If
C.received
has messages that show that: (1) the number of
agents that have committed to attack on round
r
is at least r
, and (2) the general has sent an
attack message, then C
commits to attack and sends these
messages as well as an additional message that C
has
committed to attack.
Step 2
C.received = ( (UNION over all loyal agents B of B.sent) UNION an arbitrary subset of disloyal agents)
C
receives the messages sent by loyal lieutenants and messages
sent by disloyal lieutenants.
A disloyal lieutenant, A
, can send messages to some lieutenants
that A
is committed to attack, and not send these messages
to other lieutenants.
Lieutenant C
receives attack messages from an arbitrary subset
of disloyal lieutenants.
Lieutenant C
does not know which agents are loyal and
which are disloyal.
C.received
is the set of all messages sent to
C
regardless of whether the senders are loyal or
disloyal.
C.received = {g}
.
So, the if-clause in step 1 of round 1 is True, and therefore all
loyal lieutenants commit to attack at the end of round 1.
Part 1
We first show that if any loyal lieutenant commits on roundr
then all loyal lieutenants commit by the end of round
r+1
.
A loyal lieutenant C
commits on round r
exactly when the set C.received
has at least
r
attack messages including one from the general.
So, in round r
, C.sent
has at least
r+1
attack messages including one from the general.
Therefore, the if-clause of step 1 evaluates to True in round
r+1
, and so all
loyal lieutenants commit by the end of round r+1
.
Therefore, if any loyal lieutenant commits by the end of round
t-1
then all loyal lieutenants commit by the end of round
t
.
Part 2
We next show that if no loyal lieutenant has committed by the end of roundt-1
then no loyal lieutenant commits in round
t
.
C.sent = {}
at the end
of round t-1
if no loyal lieutenant has committed to
attack.
Therefore in round t
,
C.received
is an
arbitrary subset of disloyal lieutenants.
There are at most t-1
disloyal lieutenants because there
are at most t
disloyal agents, and the general is
disloyal.
So, on round t
, the if-clause of step 1 evaluates to False.
Part 3
From parts 1 and 2, by the end of roundt
, either all loyal lieutenants commit, or no loyal
lieutenant commits.
Because C is loyal it follows the algorithm, and C commits to attack at the end of round 3 because C receives a signed attack message from the general and signed attack messages from two different lieutenants. So, in round 3, C broadcasts copies of attack messages signed by the general and attack messages signed by A and B and attack messages, and also an attack message signed by C itself. All loyal lieutenants commit to attack in round 4 because they receive attack messages signed by the general and 3 different lieutenants (A, B, C).
K. Mani Chandy, Emeritus Simon Ramo Professor, California Institute of Technology