[ Home | Class Roster | Syllabus | Status | Glossary | Search | Course Notes]
In coordinating distributed processes, it is often necessary to reach agreement about some part of the global state.
In the absence of failures, reaching agreement is relatively straightfoward, even if initially the processes disagree about some value in the state (take majority or largest or average).
Failures can be due to faulty communications or faulty processors
With faulty communications is not possible for all processes to know that the other processes have reached agreement.
With faulty processors (that still communicate), agreement is possible under certain conditions.
It can be shown that agreement in the presence of an unreliable channel is impossible.
There are n processes and at most m of them are faulty
Processes communicate directly with each other using messages
Receiving process knows the identity of sending process
Communications is reliable
Communications is synchronous (all wait to act together)
Three modes of failures
Crash fault
Omission fault
Malicious fault (aka byzantine )
The first two are detected by synchronous communications (i.e. bounded message delays)
Messages can be authenticated or not (non-authenticated are called oral)
Complexity is measured in
Time
Message traffic
storage overhead
Byzantine: single sender, all non-faulty must agree on same value
Consensus: All processes start with some value but must agree on a single value
Interactive Consistency: Vector of values, each process contributes one element. All must agree on vector
Problem | Byzantine | Consensus | Interactive Consistenc |
---|---|---|---|
who initiates the value | One processor | All processors | All processors |
final agreement | Single value | Single value | Vector of values |
byzantine: special case of interactive consistency, only one element is of interest
interactive consistency: can run "n" byzantine agreement protocols
consensus: can use interactive consistency then take majority in vector (choose default value if no majority)
byzantine: is most primitive since others can be derived from it.
byzantine: source process sends value to others then runs consensus algorithm.
Let p0, p1, p2 be the three processors, let p0 be the source. The message is one bit.
Pease showed that it is impossible to reach consensus if the number of faulty processors (m) is greater than floor((n-1)/3) and the showed an algorithm requiring (m-1) rounds of message exchanges
BASICALLY: need a clear majority from non-faulty processes. When n=3 there are only two messages used to decide. If one or more processes faulty, cannot reach majority.
Suppose P0 and P4 faulty:
Case 1: P0 sends a different value to all processors
They quickly agree that the value is unknown (no majority even with P4 malicious).
BUT could pick minimum or a default value (e.g. 0)
Case 2: P0 sends 1 to P1, P2 and P3 and 0 to P3, P4 and P5
From http://class.ee.iastate.edu/somani/cpre545/references.html
Let (Send value source target) mean that "value" was sent from the
source to the target
Let (VoteValue source target) be the value that all good processes agree was
sent from source to target
NOTE: this value must be the same for all good processes!
NOTE: does not have to be the actual value sent by the source
BGA (0): // what P0 sends to each processor // P1, P2 and P3 get on value (v1) and the others get a difference value (v2) (SEND v1 0 1) (SEND v1 0 2) (SEND v1 0 3) (SEND v1 0 4) (SEND v1 0 5) (SEND v1 0 6)
BGA (1) /* This is the value that 1 calculates */ (VOTE (SEND v1 0 1) // actual value received by 1 from 0 (VoteValue v0.2)// agreed value sent from 0 to 2 (VoteValue v0.3)// agreed value sent from 0 to 3 (VoteValue v0.4)// agreed value sent from 0 to 4 (VoteValue v0.5)// agreed value sent from 0 to 5 (VoteValue v0.6)// agreed value sent from 0 to 6
The remaining processes 2 through 6 calculate the value of their orders in a
similar manner.
Calculating "VoteValue"
BGA (2)
// This is the value that 1 calculates
(VOTE
(SEND v1 0 1) // what 1 did receive from 0
(VOTE (SEND (SEND v1 0 2) 2 1)
// 2 sends to 1 the value v1 sent by 0 to 2
(SEND (SEND (SEND v1 0 2) 2 3) 3 1)
// 3 sends to 1 the value 2 sent to 3 which it claimed was sent to it (2)
by 0
(SEND (SEND (SEND v1 0 2) 2 4) 4 1)
(SEND (SEND (SEND v1 0 2) 2 5) 5 1)
(SEND (SEND (SEND v1 0 2) 2 6) 6 1))
(VOTE (SEND (SEND v1 0 3) 3 1)
(SEND (SEND (SEND v1 0 3) 3 2) 2 1)
(SEND (SEND (SEND v1 0 3) 3 4) 4 1)
(SEND (SEND (SEND v1 0 3) 3 5) 5 1)
(SEND (SEND (SEND v1 0 3) 3 6) 6 1))
(VOTE (SEND (SEND v1 0 4) 4 1)
(SEND (SEND (SEND v1 0 4) 4 2) 2 1)
(SEND (SEND (SEND v1 0 4) 4 3) 3 1)
(SEND (SEND (SEND v1 0 4) 4 5) 5 1)
(SEND (SEND (SEND v1 0 4) 4 6) 6 1))
(VOTE (SEND (SEND v1 0 5) 5 1)
(SEND (SEND (SEND v1 0 5) 5 2) 2 1)
(SEND (SEND (SEND v1 0 5) 5 3) 3 1)
(SEND (SEND (SEND v1 0 5) 5 4) 4 1)
(SEND (SEND (SEND v1 0 5) 5 6) 6 1))
(VOTE (SEND (SEND v1 0 6) 6 1)
(SEND (SEND (SEND v1 0 6) 6 2) 2 1)
(SEND (SEND (SEND v1 0 6) 6 3) 3 1)
(SEND (SEND (SEND v1 0 6) 6 4) 4 1)
(SEND (SEND (SEND v1 0 6) 6 5) 5 1)))
// collapsing
(VOTE (v1) // what 1 did receive from 0 (v1) // voted value on what 2 received from 0 (v1) // voted value on what 3 received from 0 (v1) // voted value on what 4 received from 0 (v1) // voted value on what 5 received from 0 (v1) // voted value on what 6 received from 0 // of course this is v1 and is correct
The remaining processes 2 through 6 calculate their orders in a similar
manner.
NOTE: if one process faulty - it can tell each of the other
processes a different value
Say P4 is faulty
BGA (0): // what P0 sends to each processor // P1, P2 and P3 get on value (v1) and the others get a difference value (v2) (SEND v1 0 1) (SEND v1 0 2) (SEND v1 0 3) (SEND v1 0 4) (SEND v1 0 5) (SEND v1 0 6)
BGA (1) /* This is the value that 1 calculates */ (VOTE (SEND v1 0 1) // actual value received by 1 from 0 (VoteValue v0.2)// agreed value sent from 0 to 2 (VoteValue v0.3)// agreed value sent from 0 to 3 (VoteValue v0.4)// agreed value sent from 0 to 4 (VoteValue v0.5)// agreed value sent from 0 to 5 (VoteValue v0.6)// agreed value sent from 0 to 6
The remaining processes 2 through 6 calculate the value of their orders in a
similar manner.
Calculating "VoteValue"
BGA (2)
// This is the value that 1 calculates
(VOTE
(SEND v1 0 1) // what 1 did receive from 0
(VOTE (SEND (SEND v1 0 2) 2 1)
(SEND (SEND (SEND v1 0 2) 2 3) 3 1)
(SEND (SEND (SEND v2.4.1 0 2) 2 4) 4 1)
// value of what P2 received from P0 as reported by faulty 4 to P1
(SEND (SEND (SEND v1 0 2) 2 5) 5 1)
(SEND (SEND (SEND v1 0 2) 2 6) 6 1))
(VOTE (SEND (SEND v1 0 3) 3 1)
(SEND (SEND (SEND v1 0 3) 3 2) 2 1)
(SEND (SEND (SEND v3.4.1 0 3) 3 4) 4 1)
(SEND (SEND (SEND v1 0 3) 3 5) 5 1)
(SEND (SEND (SEND v1 0 3) 3 6) 6 1))
(VOTE (SEND (SEND v4.1 0 4) 4 1)
(SEND (SEND (SEND v4.2 0 4) 4 2) 2 1)
(SEND (SEND (SEND v4.3 0 4) 4 3) 3 1)
(SEND (SEND (SEND v4.5 0 4) 4 5) 5 1)
(SEND (SEND (SEND v4.6 0 4) 4 6) 6 1))
// p4 can tell each other process a different value or can try to split the vote
// but all the other processes will report what they receive from P4 reliably to
P1 (and they report the value
// value to P2, P3, P5 and P6)
(VOTE (SEND (SEND v1 0 5) 5 1)
(SEND (SEND (SEND v1 0 5) 5 2) 2 1)
(SEND (SEND (SEND v1 0 5) 5 3) 3 1)
(SEND (SEND (SEND v5.4.1 0 5) 5 4) 4 1)
(SEND (SEND (SEND v1 0 5) 5 6) 6 1))
(VOTE (SEND (SEND v1 0 6) 6 1)
(SEND (SEND (SEND v1 0 6) 6 2) 2 1)
(SEND (SEND (SEND v1 0 6) 6 3) 3 1)
(SEND (SEND (SEND v6.4.1 0 6) 6 4) 4 1)
(SEND (SEND (SEND v1 0 6) 6 5) 5 1)))
// collapsing
(VOTE (v1) // what 1 did receive from 0 (v1) // voted value on what 2 received from 0 (v1) // voted value on what 3 received from 0 (vP4) // voted value on what 4 received from 0 (v1) // voted value on what 5 received from 0 (v1) // voted value on what 6 received from 0 ) // VP4 could be a majority value (if P4 sent a majority the same value) // or the vote could be undecided where in vP4 = UNDECIDED value // In this case, all good processes will decide that vP4 is UNDECIDED
VOTE will return v1 regardless of the value (or not) of vP4)
Say P4 and P5 are faulty
BGA (0): // what P0 sends to each processor // P1, P2 and P3 get on value (v1) and the others get a difference value (v2) (SEND v1 0 1) (SEND v1 0 2) (SEND v1 0 3) (SEND v1 0 4) (SEND v1 0 5) (SEND v1 0 6)
BGA (1) /* This is the value that 1 calculates */ (VOTE (SEND v1 0 1) // actual value received by 1 from 0 (VoteValue v0.2)// agreed value sent from 0 to 2 (VoteValue v0.3)// agreed value sent from 0 to 3 (VoteValue v0.4)// agreed value sent from 0 to 4 (VoteValue v0.5)// agreed value sent from 0 to 5 (VoteValue v0.6)// agreed value sent from 0 to 6
The remaining processes 2 through 6 calculate the value of their orders in a
similar manner.
Calculating "VoteValue"
BGA (2)
// This is the value that 1 calculates
(VOTE
(SEND v1 0 1) // what 1 did receive from 0
(VOTE (SEND (SEND v1 0 2) 2 1)
(SEND (SEND (SEND v1 0 2) 2 3) 3 1)
(SEND (SEND (SEND v2.4.1 0 2) 2 4) 4 1)
(SEND (SEND (SEND v2.5.1 0 2) 2 5) 5 1)
(SEND (SEND (SEND v1 0 2) 2 6) 6 1))
(VOTE (SEND (SEND v1 0 3) 3 1)
(SEND (SEND (SEND v1 0 3) 3 2) 2 1)
(SEND (SEND (SEND v3.4.1 0 3) 3 4) 4 1)
(SEND (SEND (SEND v3.5.1 0 3) 3 5) 5 1)
(SEND (SEND (SEND v1 0 3) 3 6) 6 1))
(VOTE (SEND (SEND v4.1 0 4) 4 1)
(SEND (SEND (SEND v4.2 0 4) 4 2) 2 1)
(SEND (SEND (SEND v4.3 0 4) 4 3) 3 1)
(SEND (SEND (SEND v4.5 0 4) 4 5) 5 1)
(SEND (SEND (SEND v4.6 0 4) 4 6) 6 1))
(VOTE (SEND (SEND v5.1 0 5) 5 1)
(SEND (SEND (SEND v5.2 0 5) 5 2) 2 1)
(SEND (SEND (SEND v5.3 0 5) 5 3) 3 1)
(SEND (SEND (SEND v5.4 0 5) 5 4) 4 1)
(SEND (SEND (SEND v5.6 0 5) 5 6) 6 1))
(VOTE (SEND (SEND v1 0 6) 6 1)
(SEND (SEND (SEND v1 0 6) 6 2) 2 1)
(SEND (SEND (SEND v1 0 6) 6 3) 3 1)
(SEND (SEND (SEND v6.4.1 0 6) 6 4) 4 1)
(SEND (SEND (SEND v6.5.1 0 6) 6 5) 5 1)))
// collapsing
(VOTE (v1) // what 1 did receive from 0 (v1) // voted value on what 2 received from 0 (majority good processors) (v1) // voted value on what 3 received from 0 (vP4) // voted value on what 4 received from 0 (vP5) // voted value on what 5 received from 0 (v1) // voted value on what 6 received from 0 ) VOTE will return v1 regardless of the value (or not) of vP4 and vP5)
BGA (0): // what P0 sends to each processor // P1, P2 and P3 get on value (v1) and the others get a difference value (v2) (SEND v1 0 1) (SEND v1 0 2) (SEND v1 0 3) (SEND v2 0 4) (SEND v2 0 5) (SEND v2 0 6)
BGA (1) /* This is the value that 1 calculates */ (VOTE (SEND v1 0 1) // actual value received by 1 from 0 (VoteValue v0.2)// agreed value sent from 0 to 2 (VoteValue v0.3)// agreed value sent from 0 to 3 (VoteValue v0.4)// agreed value sent from 0 to 4 (VoteValue v0.5)// agreed value sent from 0 to 5 (VoteValue v0.6)// agreed value sent from 0 to 6
The remaining processes 2 through 6 calculate the value of their orders in a similar manner.
BGA (2)
// This is the value that 1 calculates
(VOTE
(SEND v1 0 1) // what 1 did receive from 0
(VOTE (SEND (SEND v1 0 2) 2 1)
(SEND (SEND (SEND v1 0 2) 2 3) 3 1)
(SEND (SEND (SEND v2.4.1 0 2) 2 4) 4 1)
(SEND (SEND (SEND v1 0 2) 2 5) 5 1)
(SEND (SEND (SEND v1 0 2) 2 6) 6 1))
(VOTE (SEND (SEND v1 0 3) 3 1)
(SEND (SEND (SEND v1 0 3) 3 2) 2 1)
(SEND (SEND (SEND v3.4.1 0 3) 3 4) 4 1)
(SEND (SEND (SEND v1 0 3) 3 5) 5 1)
(SEND (SEND (SEND v1 0 3) 3 6) 6 1))
(VOTE (SEND (SEND v2.1 0 4) 4 1)
(SEND (SEND (SEND v1.2 0 4) 4 2) 2 1)
(SEND (SEND (SEND v1.3 0 4) 4 3) 3 1)
(SEND (SEND (SEND v2.5 0 4) 4 5) 5 1)
(SEND (SEND (SEND v2.6 0 4) 4 6) 6 1))
(VOTE (SEND (SEND v2 0 5) 5 1)
(SEND (SEND (SEND v2 0 5) 5 2) 2 1)
(SEND (SEND (SEND v2 0 5) 5 3) 3 1)
(SEND (SEND (SEND v5.4.1 0 5) 5 4) 4 1)
(SEND (SEND (SEND v2 0 5) 5 6) 6 1))
(VOTE (SEND (SEND v2 0 6) 6 1)
(SEND (SEND (SEND v2 0 6) 6 2) 2 1)
(SEND (SEND (SEND v2 0 6) 6 3) 3 1)
(SEND (SEND (SEND v6.4.1 0 6) 6 4) 4 1)
(SEND (SEND (SEND v2 0 6) 6 5) 5 1)))
(VOTE (v1) // what 1 did receive from 0 (v1) // voted value on what 2 received from 0 (v1) // voted value on what 3 received from 0 (v7) // voted value on what 4 received from 0 (v2) // voted value on what 5 received from 0 (v2) // voted value on what 6 received from 0
v7 = v1, vote = v1 v7 = v2, vote = undecided value v7 = not v1 and not v2 (could be the undecided value), vote = v1
The remaining processes 2 through 6 calculate their orders in a similar
manner.
For 2 and 3 - the voted values will be identical, its own cannot be outvoted
All non-faulty processors must agree on a vector of values, each processor contributing one element of the vector.
VALIDITY: if Pi is non-faulty than the i-th element of the vector must be the initial value broadcast by Pi, otherwise it doesn't matter what value is agreed upon.
Fischer proved that with asynchronous processors and unbounded delays, no agreement if possible even if one processor is faulty (and even if fail-silent).
Step 1:
Step 2:
Step 3: all broadcast this vector
Step 4: Each form majority in i-th
location (or ? is no majority)
Books claims this results in agreement, but what if c = z, g = x,
k = y
No agreement, go another round, send vector, but what if x2=x, y2=y and z2=z? (P3 keeps switching its vote to confuse the others.)
Solution: Don't accept Pi's value from Pi more than once (force consistency of Pi's value from Pi to Pj. This in effect forces c=x=x2, g=y=y2, k=z=z2.
Step 1:
Step 2: (blanks denote no value need be sent)
Step 3: all broadcast this vector
Step 4: Each form majority in i-th
location (or ? is no majority) using value sent from Pi
previously in i-th location of Pi's new vector
Two cases, x, y and z are different
x = y but not z (and symmetrical cases of two agree)
If x=y=z, then can't catch a consistent liar.
Notice this is four simultaneous runnings of the Byzantine agreement discussed earlier.
Assignment 5: Do problems 8.1/8.2 |