February 22, 2024 4 min read A to Z Series: B Home

Byzantine Faults Without the Mystery

A Byzantine fault is the hard case where a node does not simply stop. It can answer incorrectly, inconsistently, or maliciously.

I think about Byzantine faults as the failure mode where a participant can look alive and still mislead the system. I recommend learning the idea even if most business systems only need crash, timeout, and retry handling.

Crash failure is quiet. Byzantine failure is misleading.

When I talk about "Crash failure is quiet. Byzantine failure is misleading.", I am really asking what Byzantine Faults Without the Mystery does when a message is late, duplicated, or missing.

If a service crashes, callers can retry or fail over. If a service returns a false price, signs the wrong result, or gives different answers to different callers, the caller needs a stronger rule than simple retry. That is why Byzantine tolerant systems usually need multiple independent participants and a voting rule.

Scenario from a real system

I use "Scenario from a real system" to keep Byzantine Faults Without the Mystery grounded in a real system, because abstract patterns are too easy to agree with and too hard to operate.

A risk engine asks three independent scoring nodes whether a transfer is safe. Two say deny and one says approve with an impossible score. The risk engine ignores the outlier and denies the transfer.

Guardrail in code

When I show "Guardrail in code", I want the code in Byzantine Faults Without the Mystery to reveal the production decision, not just the syntax.

This tiny vote keeps one misleading answer from deciding the transfer:

List<String> votes = List.of("deny", "deny", "approve");
long denyVotes = votes.stream().filter("deny"::equals).count();

String decision = denyVotes >= 2 ? "deny" : "manualReview";

The example does not trust one response. It waits for enough matching votes before denying the request, which is the basic shape of handling untrusted participants.

Sequence diagram: detect the misleading participant

detect the misleading participant The sequence works because the decision does not depend on one participant being honest. sd detect the misleading participant Risk Engine Risk Engine Node A Node A Node B Node B Node C Node C Ledger Ledger Ask for transferdecision. Ask for the same decision. Ask for the same decision. Only commit when enough independent answersagree.

The sequence works because the decision does not depend on one participant being honest.

Production choice

Continue the series

Written by Arunkumar Ganesan.

What I learnt is that Byzantine thinking sharpens a design question: can the system survive a participant that is wrong, not just unavailable?

#DistributedSystems #ByzantineFaults #Consensus #Reliability