Распределённые системы
Византийская отказоустойчивость
Цели урока
- Понимать разницу между Byzantine и crash faults и почему Raft/Paxos не защищают от первых
- Знать теорему 3f+1 и уметь вычислить нужное число узлов
- Понимать три фазы PBFT и зачем каждая из них нужна
- Знать где применяется BFT на практике и когда он избыточен
Предварительные знания
- Принципы работы Raft/Paxos (crash fault tolerance)
- Понятие кворума и majority voting
- Базовое понимание криптографических подписей
Ethereum DAO hack 2016: 60 млн долларов украдено не через взлом сети, а через Byzantine поведение контракта - узлы делали именно то, что написано в коде, но результат был катастрофическим. Paxos/Raft бессильны когда узлы врут.
- **Bitcoin (PoW)** - вероятностный BFT для публичной сети без доверия: 51% честных узлов гарантируют консенсус
- **Hyperledger Fabric** - PBFT для межбанковских расчётов где участники - конкуренты
- **Boeing 777** - triple-modular redundancy для защиты от radiation-induced bit flips (hardware Byzantine)
- **SpaceX Falcon 9** - 3 Flight Management Computers с Byzantine-tolerant voting
- **Facebook Diem/Libra** - HotStuff BFT как основа LibraBFT с O(N) view change
Лэмпорт и задача предателей
В 1982 году Лэмпорт, Шостак и Пиз опубликовали статью «Byzantine Generals Problem» - название придумал Лэмпорт как аналогию для труднообъяснимой проблемы. До этого проблему называли «Interactive Consistency Problem», что звучало менее запоминающе. Статья оказалась настолько влиятельной, что термин «Byzantine fault» вошёл в стандартный словарь distributed systems и используется в официальных авиационных стандартах DO-178C.
Задача византийских генералов
**Июнь 2016. Ethereum DAO смарт-контракт держит 150 млн долларов. Атакующий находит уязвимость и рекурсивно вызывает withdraw 1800 раз подряд - каждый раз получая 50 ETH до того как баланс обнуляется. Украдено 60 млн долларов.** Это не баг сети - узлы Ethereum корректно выполнили код. Это Byzantine fault на уровне логики: узел делал именно то, что написано, но намеренно деструктивно.
Лэмпорт, Шостак и Пиз в 1982 году формализовали эту проблему через военную метафору. N генералов осаждают город и должны договориться: АТАКОВАТЬ или ОТСТУПИТЬ. Общение - только через гонцов. Часть генералов - предатели, которые активно мешают консенсусу.
**Byzantine fault** - узел ведёт себя произвольно: врёт о полученных сообщениях, отправляет разные данные разным получателям, сговаривается с другими предателями. Принципиальное отличие от crash fault: молчащий узел - предсказуем, лгущий - нет.
| Тип сбоя | Поведение узла | Алгоритм защиты |
|---|---|---|
| Crash (CFT) | Узел упал и молчит - предсказуемо | Raft, Paxos - нужно 2f+1 узлов |
| Omission | Узел теряет часть сообщений - молча | Raft с таймаутами |
| Byzantine (BFT) | Узел врёт, шлёт противоречия, сговаривается | PBFT, HotStuff - нужно 3f+1 узлов |
**Paxos/Raft не защищают от Byzantine faults.** Оба алгоритма предполагают модель crash-stop: узел либо работает корректно, либо молчит. Один злонамеренный узел может сломать Raft-кластер: он может отвечать разным репликам разными данными и нарушить инвариант.
Проблема генералов иллюстрирует суть: при трёх генералах и одном предателе честные не могут достичь консенсуса. Если командующий-предатель посылает генералу A приказ АТАКА, а генералу B - ОТСТУПЛЕНИЕ, то A и B видят конфликт, но не знают кто из них получил ложный приказ.
Если использовать Raft с большим кластером, он защитит от взломанных узлов
Raft защищает только от crash faults. Один скомпрометированный узел в Raft-кластере может нарушить safety.
Raft требует 2f+1 узлов для f crash-отказов. Но алгоритм не верифицирует честность узлов - он просто подсчитывает голоса большинства. Byzantine узел голосует за неправильное значение, и кворум может принять ложное решение.
Чем Byzantine fault принципиально отличается от crash fault?
Теорема 3f+1: минимум узлов для Byzantine consensus
**Фундаментальный результат Лэмпорта, Шостака и Пиза (1982):** для достижения Byzantine consensus при наличии f злонамеренных узлов необходимо минимум 3f+1 узлов суммарно. Это математически доказанная нижняя граница - обойти её невозможно без дополнительных допущений.
**Интуиция за 3f+1:** при f Byzantine-узлах и f молчащих узлах (имитируют crash) остаётся f+1 честных голосов. Кворум составляет 2f+1. Из них как минимум f+1 - честные. Этого достаточно чтобы перевесить f предателей. Итого: f (Byzantine) + f (молчащие) + f+1 (честные) = 3f+1.
| f (предателей) | Нужно узлов (3f+1) | Кворум (2f+1) | Мин. честных в кворуме |
|---|---|---|---|
| 1 | 4 | 3 | 2 |
| 2 | 7 | 5 | 3 |
| 3 | 10 | 7 | 4 |
| 10 | 31 | 21 | 11 |
Почему 3 узла недостаточно для f=1: предположим командующий - предатель. Он посылает генералу G1 приказ АТАКА, генералу G2 - ОТСТУПЛЕНИЕ. G1 и G2 обмениваются сообщениями. G1 говорит G2: «я получил АТАКА». G2 говорит G1: «я получил ОТСТУПЛЕНИЕ». Оба видят конфликт, но оба утверждения одинаково достоверны - нет способа определить кто из трёх (Commander, G1, G2) является предателем.
При 4 узлах (3f+1 при f=1) аналогичный сценарий разрешается: кворум из 3 узлов будет содержать не менее 2 честных. Два честных узла согласуются между собой, перевешивая одного предателя.
Теорему 3f+1 можно обойти умной криптографией или надёжным железом
3f+1 - информационно-теоретическая нижняя граница, не зависящая от реализации
Доказательство Лэмпорта работает в модели без шифрования (устных сообщений). С аутентификацией (письменные сообщения - подписи) нижняя граница снижается до 2f+1, но это другая, более сильная модель угроз.
Банк строит систему подтверждения транзакций из 7 нод. Сколько Byzantine-узлов можно терпеть?
PBFT: первый практичный BFT-алгоритм
**Castro и Liskov, MIT, 1999. PBFT (Practical Byzantine Fault Tolerance) - первый алгоритм, который сделал BFT практически применимым.** До PBFT теоретические BFT-протоколы были слишком медленными для реального использования. PBFT показал overhead всего 3% по сравнению с non-BFT системами при малых кластерах.
Три фазы PBFT
**Pre-prepare:** Primary получает запрос клиента, назначает ему sequence number n и рассылает всем репликам. **Prepare:** каждая реплика, получив Pre-prepare, рассылает Prepare всем остальным. Состояние prepared достигается когда собрано 2f Prepare-сообщений. **Commit:** после prepared каждый шлёт Commit всем. После 2f+1 Commit - операция выполняется и клиент получает Reply.
**View Change:** если реплика не получает Pre-prepare вовремя - подозревает Primary. Отправляет VIEW-CHANGE с доказательствами. Новый Primary (view+1 mod N) собирает 2f VIEW-CHANGE и рассылает NEW-VIEW. Дорого: O(N^2) сообщений. Злонамеренный Primary может намеренно триггерить view changes, замедляя систему.
| Метрика | Crash-tolerant (Raft) | BFT (PBFT) | BFT (HotStuff) |
|---|---|---|---|
| Узлов для f отказов | 2f+1 | 3f+1 | 3f+1 |
| Сообщений на операцию | O(N) | O(N^2) | O(N) |
| Раунды | 2 | 3 | 3 |
| Криптография | Не нужна | MAC/подписи | Threshold signatures |
| View change | O(N) | O(N^2) | O(N) |
Почему клиент PBFT ждёт f+1 одинаковых ответов, а не одного?
BFT на практике: когда нужен и сколько стоит
**HotStuff (Facebook/Meta, 2018) решил главную проблему PBFT: O(N^2) сообщения при view change.** Ключевая идея - threshold signatures (пороговые подписи): вместо того чтобы лидер рассылал всем N^2 сообщений, каждая реплика шлёт подпись лидеру, лидер агрегирует в одну подпись и делает один broadcast. View change: O(N) вместо O(N^2). HotStuff используется в Diem/Libra и является основой LibraBFT.
| Область | Пример | Почему BFT, не Raft |
|---|---|---|
| Public blockchain | Bitcoin, Ethereum | Узлы принадлежат незнакомым людям, нет доверия |
| Permissioned blockchain | Hyperledger Fabric | Консорциум организаций - конкуренты в одной сети |
| Финансовые расчёты | SWIFT, межбанк | Защита от инсайдеров и взломанных узлов |
| Авиация/Космос | Boeing 777, SpaceX | Радиация может flip bits - hardware Byzantine |
| Critical infrastructure | Энергосети | APT-атаки на управляющие узлы |
**Большинству систем BFT не нужен.** Если все узлы под контролем одной организации - Raft достаточен и на порядок быстрее. BFT нужен когда участники не доверяют друг другу (разные организации, public network) или когда hardware failure может привести к Byzantine поведению (space, nuclear).
Практический выбор: внутренние системы (микросервисы, базы данных компании) - Raft или Paxos. Multi-org системы где участники конкурируют или не доверяют друг другу - BFT. Public blockchains используют вероятностный BFT (Bitcoin PoW, Ethereum PoS) который жертвует finality ради масштабируемости.
BFT нужен только для блокчейнов и криптовалют
BFT нужен везде где узлы контролируются разными недоверяющими сторонами или где hardware может дать Byzantine отказы
Авионика Boeing 777 использует triple-modular redundancy - классический BFT для hardware faults (радиация, битые биты). SpaceX Falcon 9 имеет 3 Flight Management Computers голосующих большинством. Это BFT задолго до блокчейна.
Стартап строит систему для расчётов между 5 банками-конкурентами. Raft или PBFT?
Вопросы для размышления
- Большинство production-систем используют Raft/Paxos без BFT. Какие конкретные условия в архитектуре компании сигнализировали бы о необходимости перехода на BFT-протокол?
Связанные уроки
- dist-09-raft — Raft is the crash-fault baseline; BFT extends it
- dist-08-paxos — Classic Paxos assumes crash faults only
- ds-03-consensus — BFT consensus is a harder variant of the consensus problem
- dist-12-consistency — BFT changes the impossibility boundaries for consistency
- crypto-28-digital-signatures