Эксплуатация и безопасность
Эксплуатация и безопасность — как биржа не падает и не теряет чужие деньги
Представьте вечер пятницы. Первый алерт: латентность matching engine на одной из торговых пар выросла со стандартных 200 микросекунд до 4 миллисекунд. Через секунду приходит второй — спред на той же паре расширился с 2 базисных пунктов до 40, маркет-мейкеры отползают от книги. Третий алерт объясняет первые два: на основном хосте matching engine один из NVMe в зеркале, куда пишется журнал событий, только что выпал из массива. RAID перешёл в деградированный режим, и каждый fsync() теперь идёт через единственный оставшийся диск — три миллисекунды вместо привычных восьмидесяти микросекунд. А пока fsync не вернулся, ордер не считается применённым. Основной узел жив, торги идут, но каждый ордер теперь упирается в диск. У вас — пара минут, чтобы решить: переключаться на резервный узел прямо сейчас или работать в деградированном режиме, пока инженеры не подменят выпавший NVMe.
Это — реальная жизнь CEX. Все восемь предыдущих разделов рассказывали о том, как устроена биржа. Этот раздел — о том, как она продолжает работать, когда что-то идёт не по плану. А идёт не по плану всегда. Вопрос только — как часто, насколько публично и сколько это стоит клиентам.
Availability: живая биржа — это всегда две биржи
Биржа, работающая на одной машине, — это не биржа. Это демо. Как только первый реальный клиент доверил ей свои деньги, у вас появляется SLA: не ронять.
Мы уже видели в разделе про matching engine, что вся горячая часть биржи — matching, book state, order sequencing — работает в одном процессе, и это правильно. Но «один процесс» не означает «одна машина». Для высокой доступности биржа держит как минимум две копии matching engine: основную и резервную.
Как их синхронизировать? Ответ, как почти везде в этом навыке, — через журнал событий.
- — обрабатывает поток ордеров
- — пишет каждое событие в журнал
- — эмитит trade events наружу
seq 1002 → FILL
seq 1003 → CANCEL
seq 1004 → FILL
...
- — читает журнал по порядку
- — прогоняет те же операции
- — держит идентичное состояние
Основной узел принимает все ордера и для каждого события — нового ордера, отмены, филла — создаёт детерминированную запись в append-only журнал: seq=..., type=..., payload=.... Только после fsync() журнала событие считается применённым. Резервный узел читает тот же журнал, прогоняет те же операции в той же последовательности и держит у себя идентичное состояние книги.
Ключевое слово здесь — детерминизм. Если основной узел на ордере seq=1002 взял блокировку на три микросекунды, а резервный — на семь, это нормально. Но если они расходятся в результате матчинга — скажем, основной дал событиям матчинга порядок A→B, а резервный B→A — всё, состояние разъезжается, и резервный узел превращается в тыкву. Чтобы этого не случилось, matching engine должен быть чистой функцией от журнала: на одном и том же входе — один и тот же выход, без обращения к системному времени, без генерации случайных чисел, без зависимости от порядка сетевых пакетов.
Это — тот самый event sourcing из архитектуры LMAX. Биржа хранит не текущее состояние книги, а последовательность событий, из которой состояние восстанавливается детерминированным проигрыванием журнала. При падении основного узла оркестратор переключает входящий трафик на резервный, который уже имеет актуальное состояние. Потеря — в худшем случае несколько ордеров, которые ещё не успели примениться: их биржа обязана отклонить с понятным кодом ошибки, чтобы клиент мог повторить.
Почему активная/пассивная пара, а не две активные? Потому что две matching engine, одновременно принимающие ордера на одну и ту же пару, — это рассинхронизация, запрограммированная архитектурно. Если обе инстанции получают ордера параллельно, то с точки зрения одной копии первым приходит один ордер, а с точки зрения другой — другой. Согласовать два таких «первым пришёл» можно только через консенсус. А консенсус — это миллисекунды там, где биржа считает время в микросекундах.
Для леджера и market data fan-out ситуация проще: эти подсистемы читают журнал и могут реплицироваться параллельно без ограничений. Matching — только одно место, где ордера выстраиваются в очередь. Именно поэтому архитектура биржи — асимметричная: hot path (matching) живёт в активной/пассивной паре, всё остальное масштабируется горизонтально.
Несколько регионов. Хорошо, а что если целый регион в AWS отваливается? Тогда в дело вступает межрегиональное переключение: в другом регионе сидит «тёплый» резерв, который тоже тянет журнал, но через межрегиональный поток с задержкой в несколько десятков миллисекунд. На его переключение тратятся минуты, а не секунды, и используют его только для катастрофических сценариев. За это платят объёмом данных и стоимостью межрегионального трафика — но альтернатива «мы в одном регионе и регион упал» в 2026 году неприемлема для любой серьёзной биржи.
Capacity: как готовиться к 10x всплескам
Биржа должна держать нормальную нагрузку в штатном режиме. Это — базовый минимум. Настоящий вопрос — что происходит, когда нагрузка внезапно становится в десять раз больше обычной.
Такие моменты случаются по двум причинам:
- Листинг популярной монеты. Биржа объявляет в твиттере: «через 10 минут открываем торги новой монеты». У скрипт-ботов запускается обратный отсчёт, розничные трейдеры бросаются перестраивать балансы, маркет-мейкеры прогревают соединения. В момент открытия торгов нагрузка — и на публичный API, и на matching engine — подскакивает в разы.
- Обвал рынка. Bitcoin летит вниз на 8% за час. Все хотят или выйти, или купить. Поток ордеров, поток отмен, поток WebSocket-подписок — всё растёт одновременно.
Правильный ответ на такие события — headroom, заложенный заранее. Биржа не должна «справляться в последнюю секунду» — она должна каждый день работать на 30–40% своей реальной ёмкости, чтобы на пике уйти в 90% и вернуться обратно. Закладка headroom — это буквально счёт за железо: биржа платит за инстансы, которые 95% времени простаивают, чтобы в оставшиеся 5% они вынесли на себе всю торговлю мира.
Есть ещё один источник головной боли: не все подсистемы масштабируются одинаково. Gateway и market data fan-out — практически линейно: добавили железа — обработали больше запросов. Matching engine — не масштабируется горизонтально для одной пары: у вас одна очередь ордеров, один инстанс, всё. Единственный способ увеличить пропускную способность matching — шардирование по символам (per-symbol sharding из третьего раздела) или более быстрая машина для конкретного символа. Если листят популярную монету — ей часто выделяют отдельную физическую ноду.
Что биржа делает перед анонсом, который она контролирует (листинг):
- Прогревает пулы соединений. Gateway заранее поднимает воркеры, WebSocket сервера открывают сокеты заранее.
- Изолирует новую пару. Поднимает отдельный matching engine instance, чтобы всплеск на BTC/NEW не затронул BTC/USDT.
- Отключает дорогие фичи. Временно отключает сложные отчёты, медленные административные выгрузки, всё, что не критично для торговли.
- Увеличивает лимиты на ряд подсистем и уменьшает лимиты на некоторые API, чтобы скрипт-боты не смогли сожрать весь rate limit.
- Подключает on-call. Старшие SRE и инженеры matching engine сидят в видеозвонке и смотрят дашборды.
То, что не контролируется (обвал рынка), — это проверка на то, правильно ли биржа заложила headroom за последние 12 месяцев. Биржа, которая падает под таким событием, рискует не только деньгами сегодня, но и клиентами навсегда: «она легла, когда мне надо было выйти» — это самое неприятное воспоминание, которое остаётся у пользователя о любой бирже.
Security: defense in depth
Слова «безопасность CEX» обычно вызывают в голове одну ассоциацию — кошельки. Это правильно, но слишком узко. Настоящая модель безопасности биржи — это defense in depth: много слоёв, каждый защищает следующий, и атакующий должен пробить все, чтобы добраться до денег.
Разберём слои изнутри наружу.
1. Холодное хранение. Основная масса клиентских активов — в кошельках, которые физически отключены от сети. Их ключи не хранятся на серверах биржи вообще; они лежат в сейфе в отдельной юрисдикции, и для подписания транзакции требуется ручная процедура с m-из-n подписантами. Это самый последний барьер: даже если взломали всё остальное, из холодного кошелька украсть нельзя без того, чтобы атакующий оказался физически у сейфа с нужным числом подписантов.
2. HSM или MPC для «рабочих» ключей. Для hot и warm кошельков, из которых биржа ежедневно платит выводы, приватные ключи не лежат в файле на сервере. Они живут либо в hardware security module (HSM) — выделенном устройстве, которое физически не отдаёт ключ наружу, только подпись, — либо в multi-party computation (MPC) схеме, где «ключ» разделён между несколькими серверами и никто в одиночку не может его восстановить. Это защита от компрометации одного сервера: взломали машину — ключа там всё равно нет.
3. Авторизация. Каждый API-запрос проходит через проверку: что делает запросивший, имеет ли он на это право, не превышает ли он лимиты. Роли, scopes, права API-ключей, rate limits — всё это сидит здесь. Самая частая ошибка уровня «security 101» — забыть проверить авторизацию на каком-нибудь редком административном endpoint'е, через который потом кто-то получает доступ к чужому аккаунту.
4. Аутентификация. Прежде чем что-то авторизовывать, нужно знать, кто пришёл. Для клиентского UI — OAuth, WebAuthn, обязательный 2FA. Для API — ключ плюс HMAC-подпись с timestamp (мы видели этот паттерн в разделе 8). Для сотрудников биржи — SSO, обязательные hardware-токены, короткие сессии. Пароли — только как один фактор из многих, и никогда единственный.
5. Периметр сети. Всё, что выше, защищается внешним слоем: WAF от типичных атак, DDoS-защита от объёмных атак, сегментация VPC — чтобы даже если атакующий пробился через frontend, он не смог дойти до matching engine по внутренней сети. Администраторские интерфейсы — вообще в отдельной сети, доступной только через VPN с hardware-токеном.
Главное в defense in depth — асимметрия в пользу защитника: чтобы добраться до денег, атакующему нужно пробить все слои подряд; защитнику достаточно, чтобы хотя бы один из них удержал. Но эта асимметрия работает только при одном условии: каждый класс атак реально перекрыт хотя бы одним слоем. Если в архитектуре пропущен слой, который должен был ловить конкретный вектор, — для этого вектора у вас просто нет защиты, сколько бы других слоёв вы ни выстроили вокруг. Поэтому пропущенный слой — это не «чуть хуже»; это потенциальная дыра на всю стоимость актива.
И ещё один момент, о котором часто забывают: observability — часть безопасности. Если вы не видите, что кто-то пробует подбирать ваши API-ключи по брутфорсу, вы не заметите саму попытку. Аудит-логи, SIEM, алерты на аномальный доступ, мониторинг outbound traffic — всё это не «фичи безопасности», это основа.
KYC и AML
Прежде чем углубляться, расшифруем две аббревиатуры, которые в дальнейшем будут везде.
KYC — Know Your Customer, «знай своего клиента». Набор процедур, которыми биржа удостоверяется, что за каждым аккаунтом стоит реальный человек или компания: паспорт, селфи, подтверждение адреса проживания, иногда — источник средств. Цель — не дать анонимам, подсанкционным лицам и подставным аккаунтам открыть счёт.
AML — Anti-Money Laundering, «противодействие отмыванию денег». Это уже про поведение клиента после регистрации: отслеживание транзакций, поиск подозрительных паттернов, проверка адресов на связь с криминальными источниками, передача данных в финансовую разведку. Если KYC отвечает на вопрос «кто», то AML — на вопрос «что этот кто-то делает с деньгами».
Эти два слоя работают в связке: KYC даёт идентичность, AML наблюдает за действиями этой идентичности во времени. По отдельности они дырявы — KYC без AML пропускает легально открытый счёт, через который потом гонят грязные деньги; AML без KYC видит подозрительные транзакции, но не может никому их пришить.
Этот раздел не о юриспруденции. Он о том, что KYC и AML — это не про «правила комплаенса», а про реальный инженерный слой, через который проходит каждый клиент и каждая транзакция. И если он сломан — биржа в лучшем случае получит штраф, в худшем — лишится лицензии в юрисдикции и потеряет доступ к фиатной инфраструктуре.
На высоком уровне поверхность состоит из трёх слоёв:
- Идентификация на входе. Регистрация аккаунта, сбор документов, верификация паспорта и селфи, проверка адреса проживания, связь с санкционными списками (OFAC, UN, EU). Это — воронка KYC, обычно разделённая на уровни (tiers), где каждый уровень открывает новые возможности.
- Непрерывный мониторинг транзакций. Каждый депозит, вывод, внутренний перевод проходит через transaction monitoring: на какой адрес отправляется, связан ли он с известными рисковыми адресами и организациями (миксеры, darknet-маркеты, известные кошельки санкционных стран), не похож ли паттерн на структурирование (разбивку крупной суммы на мелкие для обхода порогов), не меняется ли поведение клиента резко.
- Отчётность и взаимодействие с регуляторами. Подача SAR (suspicious activity reports), ответы на запросы правоохранительных органов, выполнение travel rule (FATF Recommendation 16) — передача данных об отправителе и получателе при межбиржевых переводах выше определённого порога.
Для инженера здесь важны две вещи.
Первое — KYC не делается один раз. Он переходит в continuous re-KYC: если клиент не обновлял документы три года, биржа обязана попросить их заново. Если клиент вдруг начал получать депозиты с адресов, которые появились в санкционном списке после его регистрации — его нужно ограничить автоматически, а не через месяц, когда комплаенс-команда прочтёт отчёт. Всё это — отдельная очередь событий с отдельными SLA.
Второе — tiered KYC влияет на всю остальную систему. Лимиты торговли, доступность фиатных рельс, доступ к деривативам, возможность открывать sub-accounts — всё зависит от KYC tier. Эта информация используется десятком других подсистем, и её консистентность важна не меньше, чем консистентность баланса. Если один сервис видит пользователя как tier 2, а другой — как tier 0, это прямая дыра, через которую кто-нибудь обязательно пролезет.
Travel rule, санкционные проверки, мониторинг — всё это стоит денег и замедляет UX. Соблазн «упростить» огромен. Уроки последних десяти лет единообразны: биржи, которые не соблюдают KYC и AML на серьёзном уровне, либо сами исчезают под санкциями (BitMEX, затем более мелкие), либо лишаются банковских партнёров и не могут работать с фиатом. Комплаенс — не «налог на скорость», это инженерное требование, без которого продукт не существует в юрисдикциях, где живёт большинство пользователей.
Incident response: биржа не лжёт, биржа чинится
Хорошая биржа — это не биржа без инцидентов. Это биржа, которая умеет их замечать, их останавливать и честно рассказывать о произошедшем.
Протокол incident response обычно состоит из четырёх фаз:
- Detection. Алерт пришёл. Кто на дежурстве — начинает работу. Первая задача — понять, что именно видно в мониторинге, и присвоить инциденту серьёзность (S1 — все клиенты не могут торговать, S2 — часть клиентов, S3 — деградация).
- Containment. Остановить распространение. Для matching engine это может означать «остановить торги по одному символу», для wallet-сервиса — «приостановить выводы в одну сеть», для API — «включить жёсткий rate limit». На этом этапе важнее остановить кровь, чем найти причину.
- Remediation. Починить. Это может занять от минут до дней. Параллельно — коммуникация с клиентами: биржа, которая молчит во время инцидента, теряет доверие быстрее, чем биржа, которая честно пишет «работаем над проблемой». Статусная страница обновляется в реальном времени.
- Post-mortem. После того как инцидент закрыт, — публичный разбор. Что случилось. Почему. Что мы делаем, чтобы это не повторилось. Хорошие post-mortems — это документы на несколько страниц с таймлайном, root cause analysis, списком action items. Плохие — «Dear customer, we experienced a technical issue».
Некоторые инциденты требуют особых действий, которые биржа должна иметь в арсенале заранее, а не придумывать на ходу:
- Halt a symbol. Остановить торги по одной паре. Все существующие ордера — либо остаются, либо отменяются (зависит от политики). Новые не принимаются. Это делается, когда на символе «что-то не то» — аномальная цена, подозрение на манипуляцию, проблема с оракулом.
- Trade bust. Откатить сделки. Крайне спорное действие: биржа фактически отменяет уже исполненные сделки и возвращает балансы. Должна применяться только в вопиющих случаях (fat-finger на порядок больше обычного объёма), и правила bust'а должны быть опубликованы заранее.
- Disclose a breach. Если произошёл взлом кошелька или утечка персональных данных — раскрыть публично. Быстро, честно, с оценкой ущерба. Попытки «подождать и понять масштаб» почти всегда оборачиваются тем, что новость выходит не от биржи, а от злоумышленника или от журналиста.
Incident response — это культура, а не процесс. Биржа, где инженеры боятся рассказать о своей ошибке, потому что «накажут», — биржа, где следующая ошибка случится через неделю и будет хуже. Биржа, где ошибки обсуждаются открыто и анализируются без поиска виноватых, — биржа, где инженеры вовремя признают «я сломал» и цикл устранения короче.
Регулирование как архитектурное требование
Инженер CEX быстро узнаёт, что регулирование — это не «то, о чём думают юристы». Это вторая половина технического задания.
- Travel rule. При переводе между биржами выше определённой суммы (обычно $1 000 или $3 000 в зависимости от юрисдикции) отправляющая биржа должна передать получающей информацию об отправителе. Для этого биржа подключается к сетям вроде TRP, Sumsub, Notabene — и этот протокольный слой сидит в потоке вывода. Если он сломан — вывод заблокирован.
- Record retention. Все ордера, все сделки, все сообщения поддержки, все изменения KYC — должны храниться минимум 5–7 лет (зависит от юрисдикции). Это — прямое влияние на архитектуру базы данных и на стратегию холодного хранилища.
- Отчёты регуляторам. Ежедневные, ежемесячные, ежеквартальные выгрузки. Биржа должна уметь достоверно сформировать отчёт за любой период, и тот должен сходиться с внутренним леджером копейка в копейку.
- MiCA в ЕС, CFTC и SEC в США, FCA в UK, MAS в Сингапуре. Каждая юрисдикция добавляет свои правила. Некоторые требуют отдельного юридического лица в юрисдикции; некоторые — отдельного ледгера для клиентов из юрисдикции; некоторые — отдельного API-endpoint'а. Биржа, работающая глобально, быстро обнаруживает, что ей нужна не одна архитектура, а набор сегментированных архитектур под каждый рынок.
Это влияет на архитектуру намного глубже, чем кажется на первый взгляд. Простой пример: если MiCA требует, чтобы клиентские фиатные средства хранились на отдельном счёте в отдельном банке (обычно так и есть), это значит, что внутренний леджер биржи должен уметь для каждого пользователя отслеживать, в каком именно банке находятся его евро — и уметь это отразить в отчёте.
Короткая мораль: регулятор — один из стейкхолдеров архитектуры, не «внешний раздражитель». Чем раньше инженер это примет, тем меньше будет переписываний в будущем.
Собираем всё вместе — и смотрим вперёд
Мы прошли девять разделов, каждый — про один кусок биржи: блокчейн-основы, философия, архитектура, matching engine, жизненный цикл ордера, леджер, кастоди, market data, эксплуатация. Это не лестница, по которой нужно подниматься снизу вверх, и не башня, где первый этаж держит на себе остальные. Это контур одной системы, в которой подсистемы взаимно опираются друг на друга. Matching engine не имеет смысла без журнала событий; журнал — без двойной записи; двойная запись — без сверки с on-chain-резервами; сверка — без сканера депозитов; сканер — без понимания, как блокчейн договаривается о консенсусе. Слабость в одной точке не остаётся локально: она протекает наружу и делает уязвимым всё, что от этой точки зависит.
У всех крупных крахов бирж за последнее десятилетие есть одно общее свойство: ни одна из этих бирж не понимала собственную архитектуру до конца. Кто-то не понимал инварианты блокчейн-протокола, на котором работал. Кто-то не понимал, что отсутствие двойной записи — это не «баг отчётности», это отсутствие биржи как понятия. Кто-то не понимал, что multi-party control без разных каналов верификации — это single-party с более длинным названием. А те, кто выживал, обычно выживали не потому, что понимали лучше, а потому что их команда правильно реагировала после удара.
Цель этого навыка — чтобы, когда вы (или ваш AI-агент) будете строить, поддерживать, отлаживать или проектировать биржу, у вас была не «насмотренность», а структурированная модель. Модель, в которой каждый термин — matching engine, hot path, cold storage, double-entry, snapshot+delta, активная/пассивная пара, defense in depth — имеет не расплывчатое значение, а конкретное. Модель, в которой, услышав «у нас гэпы в стакане», вы автоматически вспоминаете раздел 8 и знаете, куда смотреть. Модель, в которой, услышав «у нас расходится баланс на $47», вы автоматически вспоминаете раздел 6 и знаете, какие счета сверять.
Что осталось за кадром: деривативы
Всё, о чём мы говорили, — спотовая торговля. Клиент покупает актив по текущей цене и владеет им. У современных бирж есть ещё деривативы: фьючерсы, бессрочные контракты (perpetual swaps), опционы, с плечом, с ликвидациями, с индексами финансирования. По объёму деривативы на большинстве крупных CEX превышают спот в несколько раз.
Архитектура деривативов добавляет целый новый ряд подсистем: risk engine с постоянной переоценкой позиций и маржи, liquidation engine, funding rate calculator, insurance fund, index price oracle — и всё это должно работать в той же hot-path-парадигме, что и matching engine. И граница между типами отказов там размывается: операционный сбой на деривативной бирже может мгновенно превратиться в кризис платёжеспособности, потому что невыплаченные ликвидации накапливают системный риск гораздо быстрее, чем расходящийся на копейки спот.
Дополнительное чтение
- FATF — Virtual assets and travel rule — основной регуляторный источник по AML-требованиям для CEX
- Kraken engineering blog — один из немногих публично доступных блогов, где инженеры CEX честно пишут об архитектуре, отказах и масштабировании
Если хочется конкретики по тому, как биржи разоряются на практике, четыре документа закрывают весь спектр причин:
- FTX Chapter 11 First Day Declaration (John J. Ray III, 2022-11-17) — как выглядит отсутствие бухгалтерии в продукте, который бухгалтерией должен быть
- DOJ press release on Bitfinex hacker sentencing (2024) — итог восьмилетнего расследования крупнейшего криптоизъятия в истории
- Wikipedia: 2024 WazirX hack — наиболее полный публичный свод источников по атаке Lazarus на индийскую биржу
- Ontario Securities Commission — QuadrigaCX report (PDF) — разбор того, как понци-схема маскировалась под биржу с «потерянным ключом»