Кастоди и кошельки
Возьмите любую крупную биржу и задайте простой вопрос: где прямо сейчас лежат ваши деньги? Ответ неудобный — на бумаге у вас есть строка в базе данных биржи, а на самом деле ваши сатоши смешаны с сатошами ещё нескольких миллионов человек и лежат в горстке кошельков, ключи от которых вы никогда не видели. Этот раздел целиком про то, как эта конструкция устроена изнутри: какие кошельки есть, кто их подписывает, как деньги через них входят и выходят, и главное — какие катастрофы случаются, когда одно из звеньев ломается.
Напомним главное правило из первого раздела: внутри биржи всё происходит off-chain, в её собственном леджере. Блокчейн нужен ровно в двух местах — на депозите и на выводе. Кастоди — это и есть инженерия этих двух мест, плюс хранилища, где лежат криптовалюты.
Три температуры: hot, warm, cold
Первое, что понимает любой инженер биржи: нельзя держать все деньги в одном месте. Если приватный ключ для всех клиентских средств живёт в одной машине с доступом в интернет — этот ключ рано или поздно украдут. Не потому что админы глупые, а потому что любая система в сети рано или поздно ломается. Это вопрос времени.
Прежде чем говорить про «температуры», давайте проговорим одну скучную, но важную вещь. С точки зрения блокчейна у биржи нет никаких специальных «биржевых кошельков». Есть ровно те же самые обычные адреса, которые может завести любой человек у себя на ноутбуке: пара «приватный ключ — публичный адрес», с него можно принимать монеты и, если подписать транзакцию приватным ключом, — отправлять. Блокчейн не отличает адрес Binance от адреса вашего друга Ержана: это просто строка, за которой стоит ключ. Всё, чем биржа от Васи отличается, — у неё таких адресов не один, а много, и она сознательно держит ключи в разных условиях, чтобы атаковать все сразу было невозможно.
Вот эти «разные условия» и называются температурами. Слово взято по аналогии с физикой: «горячее» — то, с чем постоянно работают руки (и что легко обжечь), «холодное» — то, что лежит в сейфе и чего касаются редко. Никакого отдельного протокола, отдельного типа кошелька или отдельной криптографии за температурами не стоит. С точки зрения блокчейна все три уровня — обычные адреса, ничем друг от друга не отличающиеся. Разница только в том, где физически лежит приватный ключ и что должно произойти, чтобы им воспользоваться:
- У горячего адреса ключ живёт на сервере, который подключён к интернету 24/7 и подписывает транзакции сам, без участия человека. Украсть такой ключ сложно, но принципиально возможно — именно потому, что он доступен для подписи в любой момент.
- У тёплого ключ лежит в более защищённом окружении (отдельный сервис с ограниченным доступом, multisig или MPC), подпись всё ещё автоматизирована, но чтобы её получить, нужно пройти дополнительные проверки.
- У холодного ключ физически отрезан от сети — живёт на аппаратном модуле в сейфе, и чтобы подписать им хотя бы одну транзакцию, нужно физически прийти в ту комнату, где этот модуль стоит, и провести ручную процедуру под камерами.
Именно эта разница — от «ключ подписывает сам» до «ключ подписывает только коллективно и под запись камер» — и задаёт уровни удобства и риска. Поэтому биржи раскладывают средства по трём уровням — hot, warm, cold — с разным компромиссом между «удобством» и «риском».
Логика очень простая:
- Hot — это небольшой буфер, который нужен, чтобы обслуживать ежедневный поток выводов. Если всё, что там лежит, украдут за одну ночь — биржа переживёт. Именно поэтому hot стараются держать в районе пары процентов от общего объёма.
- Warm — полу-изолированное хранилище. Ключи не висят в открытом интернете, но подпись всё ещё автоматизирована (multisig или MPC). Warm подпитывает hot, когда тот истощается.
- Cold — глубокое хранилище, физически отрезанное от сети. Подпись требует человека (иногда — нескольких человек), сейф, HSM, процедуру под запись камер, а иногда — полёт в другой город. Задержка — часы или сутки, зато риск близок к нулю.
Запомните эту пропорцию: ~3% hot, ~10% warm, ~87% cold. Конкретные числа плавают — после крупного хака биржи становятся ещё консервативнее, а в спокойные периоды могут расслабиться. Но порядок величин именно такой.
Кейс: Mt. Gox и уроки первой катастрофы
В феврале 2014 года Mt. Gox — в своё время крупнейшая биткоин-биржа, через которую проходило до 70% мирового оборота — объявила о пропаже ≈850 000 BTC. Катастрофа была не в одном взломе: средства утекали годами, по чуть-чуть, а внутренний учёт был настолько дырявым, что сама биржа узнала о масштабах только когда пересчитала cold-кошельки.
Постфактум стало ясно: Mt. Gox почти не использовала разделение на температуры. Приватные ключи лежали там, где их было удобно использовать, и туда же имели доступ сервисы, обрабатывающие депозиты. Вся современная дисциплина «hot/warm/cold» — это прямой ответ на эту историю. Сегодня любая серьёзная биржа обязательно демонстрирует регуляторам структуру хранения — не потому что кто-то этого требует, а потому что индустрия запомнила урок.
(История Mt. Gox также связана с технической дырой — transaction malleability*. О ней мы вспомним чуть ниже, в разделе про сканеры депозитов.)*
Сканер депозитов: как деньги попадают на биржу
Представьте, что вы пользователь. Вы копируете из интерфейса адрес вида bc1q…x7k, вставляете его в свой холодный кошелёк, отправляете 0.5 BTC. Через 5 минут заходите на биржу — баланс пока пуст. Через 15 минут — всё ещё пуст. Через полчаса — зачислено. Что произошло за эти полчаса?
За кулисами работает сканер депозитов — отдельный сервис (или несколько), который делает всего три вещи:
- Слушает новые блоки у своих bitcoin-нод (своих — не чужих, это важно).
- Для каждого блока ищет транзакции, у которых хотя бы один output ведёт на известный биржевый адрес.
- Когда нужная транзакция получает достаточно подтверждений, сканер посылает в леджер команду «зачислить 0.5 BTC пользователю user_001».
Важная деталь: зачисление НЕ происходит в момент, когда транзакция попала в блок. Оно происходит, когда транзакция набрала порог подтверждений, который биржа установила для конкретной сети. Мы уже обсуждали этот порог в первом разделе, где разбирали глубину подтверждений, и возвращались к нему в разделе про леджер, когда говорили про суспенс-счета и мосты между on-chain и off-chain, — здесь мы видим, как он применяется в реальном сервисе.
Почему нельзя зачислять раньше? Потому что существует риск reorg — ситуация, когда часть сети добыла конкурирующую цепь блоков, и она оказалась длиннее. В этот момент ваша транзакция «выпадает» из канонической цепи, словно её и не было. Если биржа уже зачислила баланс и пользователь успел вывести средства в другую монету — это прямой убыток биржи. Классический double-spend.
Именно поэтому пороги подтверждений для дорогих монет так высоки:
- BTC — типично 3 подтверждения на крупных биржах, ~30 минут.
- ETH — 12–64, зависит от суммы и политики биржи.
- Быстрые сети (Solana, Tron) — свой порог, часто основанный не на блоках, а на финализации слота.
Подводный камень: transaction malleability у Mt. Gox
А теперь вернёмся к истории Mt. Gox. Часть пропаж Mt. Gox списывали на malleability — свойство старого формата биткоин-транзакций, позволяющее сторонним узлам менять txid, не меняя семантики перевода. Атакующий запрашивал вывод, ловил транзакцию в mempool, публиковал её же с изменённым id, и когда исходный txid не появлялся в блокчейне — возвращался к бирже с жалобой «вывод не дошёл». Плохо написанный сканер, который следил именно за txid, а не за выходами транзакции, не мог отличить повторный запрос от легитимного.
Решение пришло только спустя несколько лет — с SegWit (BIP-141), который разделил подпись и данные транзакции. Но до SegWit биржам пришлось строить костыли: отслеживать не txid, а именно выходы, и никогда не верить «вслепую» собственным исходящим транзакциям. Это один из тех случаев, когда технический просчёт одного формата блокчейна сломал целую компанию.
Вывод средств: конвейер из восьми стадий
Если депозит — это «три шага и немного терпения», то вывод — это полноценный конвейер с восемью стадиями, на каждой из которых можно что-то сломать.
Обратите внимание на три места, которые новички обычно пропускают:
- Риск-скоринг (стадия 2). Whitelist-адресов, лимиты, поведенческие сигналы, AML-флаги. Если что-то «не так» — заявка уходит в ручную проверку. Большая часть выводов, задержанных на сутки, сидит именно здесь.
- Батчинг (стадия 4). Биржа НЕ отправляет каждый вывод отдельной транзакцией. Это было бы сумасшедше дорого. Вместо этого выводы копятся в течение окна (минуты — часы) и агрегируются.
- Подпись в HSM (стадия 5). Приватный ключ никогда не покидает защищённый модуль. Сервис, формирующий транзакцию, отправляет её в HSM и получает подпись — и больше ничего. Это критически важно: если взломают машину, формирующую запросы, ключи всё ещё остаются в HSM.
Батчинг: одна транзакция на десятки пользователей
Батчинг — это нормально и ожидаемо. Если вы увидите в блокчейне большую транзакцию с 50–200 выходами, идущую из известного биржевого кошелька — это не «биржа что-то странное делает», это повседневная оптимизация. Платой за батч становится задержка: до отправки нужно дождаться закрытия окна. Для срочных выводов существует платный «priority» канал, который выходит отдельной транзакцией вне батча.
Кейс: Bitfinex 2016 — 119 754 BTC и принцип «один hot не должен весить столько»
2 августа 2016 года биржа Bitfinex сообщила о пропаже 119 754 BTC из мультиподписных кошельков, которые она делила со своим партнёром по кастоди BitGo. Атакующим удалось провести подписанные транзакции через систему, которая формально выглядела как 2-of-3 multisig. На тот момент — больше $70 млн, а по ценам 2024 года — уже больше $4,5 млрд.
Главный урок Bitfinex — даже правильные слова («multisig», «2-of-3», «HSM») не защищают, если слишком большая доля активов физически доступна горячему процессу. После этого взлома индустрия окончательно закрепила принцип: hot должен весить минимум, сколько нужно на сутки выводов, и ни копейкой больше. Излишки — вниз по температурной лестнице.
История Bitfinex закрылась только в 2022 году, когда ФБР объявило о возврате большей части украденного. Супруги, отмывавшие средства, были осуждены: Илья Лихтенштейн получил пять лет в 2024 году, Хизер Морган — полтора.
HD-кошельки: один seed, миллион адресов
Теперь отложим политику доступа в сторону и поговорим об устройстве входной двери. Каждый пользователь биржи должен увидеть в интерфейсе свой личный депозитный адрес. Если все шлют BTC на один общий адрес — учёт мгновенно превращается в детектив: «эти 0.4 BTC в блоке 800123 — от кого из 312 человек, которые за последний час заявили, что собираются пополнить счёт?». По txid и по сумме гадать бессмысленно, это не идентификатор. Единственный надёжный способ приклеить депозит к конкретному пользователю — выдать каждому свой уникальный адрес и ждать прихода именно на него.
Представим инженера по имени Валера, который приходит в биржу в 2013 году и видит, как этот вопрос решался «в лоб»: есть таблица user_wallets с колонками user_id, address, private_key_encrypted. Каждый раз, когда регистрируется новый пользователь, сервис генерирует новый приватный ключ, выводит из него адрес и сохраняет оба в базе. Через полгода в этой таблице уже 800 тысяч строк. Каждая строка — это отдельный приватник, который нужно шифровать, бэкапить, ротировать, защищать от кражи. Регулятор приходит и спрашивает: «Покажите, как у вас устроена процедура backup'а приватных ключей?» — и Валера понимает, что честный ответ звучит как «у нас 800 000 секретов, каждый копируется в три региона, и если хоть один из них утечёт — у нас украдут всё, что лежало на соответствующем адресе». Это системная катастрофа, ожидающая своего дня. Значит, надо что-то придумать.
В том же 2013 году Питер Вуйлль публикует BIP-32, и он буквально написан ради этой задачи. Идея звучит как магия, но на самом деле это аккуратная криптоарифметика. Берём один случайный секрет — мастер-seed — и из него детерминированно выводим целое дерево ключей. Для любого пути вида m/a/b/c/d/... выводится свой приватный и свой публичный ключ, однозначно определяемые seed'ом и этим путём. В результате 800 000 отдельных секретов схлопываются в один мастер-seed, который нужно бэкапить и защищать. Все остальные ключи — производные, их можно пересчитать в любой момент.
Как Валера раздаёт адреса миллиону пользователей
Представим, что Валера уже внедрил BIP-32. Что происходит, когда на биржу приходит миллион первый пользователь?
Сначала один раз в cold-окружении Валера сгенерировал мастер-seed — 256 случайных битов, которые в читаемом виде записаны как BIP-39-mnemonic из 24 слов. Эти 24 слова в буквальном смысле напечатаны на листе бумаги, запечатаны в конверт, отвезены в депозитарий и разрезаны на три Shamir-части (это уже SLIP-39, отдельная спецификация). На сервере никаких 24 слов никогда не лежит. Это единственное, что нужно хранить в абсолютной секретности — всё остальное из них выводится.
Из мастер-seed Валера один раз выводит путь m/44'/0'/0' — это аккаунт в терминологии BIP-44: конкретная ветка дерева, которая «принадлежит» сегменту «депозиты пользователей в BTC». На этом уровне у него появляются две вещи: расширенный приватный ключ xpriv (extended private key) и расширенный публичный ключ xpub (extended public key). xpriv остаётся в cold-хранилище, никуда оттуда не уходит. А вот xpub Валера выкладывает в hot-сегмент — в тот самый сканер депозитов, который слушает блокчейн и прикладывает входящие транзакции к пользователям.
И вот здесь начинается магия BIP-32. Из xpub (без приватника!) можно детерминированно получить все публичные ключи-потомки: m/44'/0'/0'/0/0, m/44'/0'/0'/0/1, m/44'/0'/0'/0/2, и так далее. Это значит, что когда регистрируется user_1000001, биржа:
- Берёт
xpubдеплозитной ветки из памяти сканера. - Прибавляет индекс
1000001к хвосту пути (m/44'/0'/0'/0/1000001). - Детерминированно вычисляет публичный ключ на этой позиции.
- Из публичного ключа получает адрес (
bc1q…q4m2). - Показывает этот адрес в интерфейсе.
Приватник к этому адресу никто не вычислял. Он существует в теории: если взять xpriv из cold-хранилища и применить ту же операцию — родится соответствующий приватный ключ. Но пока никому не нужно никакого вывода, никому не нужно и тревожить cold. Депозит работает полностью с публичной стороной.
Когда приходит транзакция на bc1q…q4m2, сканер видит её в блоке, сверяется со своей локальной картой «адрес → user_id» и говорит леджеру: «начисли 0.5 BTC пользователю 1000001». Весь этот конвейер — ровно то, что мы разобрали в разделе про сканер депозитов. HD-кошельки — это то, что делает его возможным: сканер знает все будущие адреса, но не может ни одного из них потратить.
Разбираем путь: что значит m/44'/0'/0'/0/1000001
BIP-32 сам по себе не навязывает никаких значений узлам — он только определяет правила вывода. Но индустрия договорилась об общем словаре через BIP-44, и теперь любой кошелёк, любая биржа, любое железо понимают одни и те же позиции:
m— сам мастер-ключ, корень дерева.44'— purpose. Штрих (apostrophe) означает hardened derivation: производная, которая требует приватной части и не может быть выведена только из родительского xpub.44'намертво прибит к BIP-44 — то есть «мы используем стандартную схему с coin_type и аккаунтами».0'— coin_type.0= Bitcoin,60= Ethereum,501= Solana, полный реестр живёт в SLIP-44. Разные монеты изолированы друг от друга: компрометация одного аккаунта в ETH-поддереве не трогает BTC-поддерево, потому что они выводятся через разные hardened-узлы.0'— account. У Валеры таких аккаунтов может быть много: один для пользовательских депозитов, другой для hot-кошелька биржи, третий для warm-кошелька, четвёртый для юридического лица из другой юрисдикции. Hardened-штрих здесь означает, что узнав xpub одного аккаунта, нельзя вычислить xpub соседних — аккаунты изолированы.0— change. Без штриха.0— внешние адреса (те, которые мы выдаём пользователям),1— change-адреса (те, куда идёт сдача от наших же исходящих транзакций). Для бирж change-ветка тоже важна, потому что каждый вывод оставляет сдачу, и она должна попадать обратно на контролируемый адрес.1000001— собственно индекс пользователя. Без штриха — это soft derivation, и именно она позволяет вычислять адрес из одного только xpub, без приватника.
Граница между hardened (/44') и soft (/0/1000001) — это и есть граница секретности. Всё, что до этой границы, требует приватной части и живёт в cold. Всё, что после, можно без риска вычислять в горячем сегменте, потому что для этих узлов достаточно xpub. Именно поэтому account (0') идёт с hardened, а change и индекс — без.
Почему это большой инженерный выигрыш
Вернёмся к Валере и его таблице на 800 000 строк. После перехода на HD-кошельки в cold-хранилище лежит один мастер-seed. В hot-сегменте, в сканере, лежит один xpub на депозитную ветку. Адреса генерируются на лету из индекса пользователя. Что получается:
- Бэкапить нужно один секрет, а не 800 000. Процедура резервного копирования схлопывается до «распечатать мнемонику, шамировать, развезти по сейфам». Один раз, а не каждый день.
- Компрометация сканера — это плохо, но не катастрофа. Допустим, атакующий украл xpub. Он теперь знает все депозитные адреса и может смотреть балансы пользователей в блокчейне (приватность тоже важна, так что это неприятно). Но он не может подписать ни одной транзакции: для этого нужен
xpriv, а тот лежит в cold, которого атакующий не касался. Сравните с миром «таблицы на 800 000 приватников»: там успех атакующего означал бы миллионы украденных биткоинов. Здесь — только чтение. Эту асимметрию оплатили очень дорого в эпоху до BIP-32, и именно она — фундамент современной кастоди-архитектуры. - Детерминированность. Если сервер упал, база потерялась или кто-то что-то случайно удалил — адреса можно восстановить. Они не хранятся, они вычисляются. Знаете seed — значит, умеете воспроизвести всё дерево.
- Единый формат для всех монет. Поддержка новой монеты — это новый
coin_typeв дереве. Не «ещё один отдельный сервис управления ключами», а ещё один узел под тем же корнем. Для Валеры это означает, что добавление USDC или Solana не требует нового кошелькового стека — только нового кода вывода адресов в стандарте BIP-32/SLIP-44.
Что мы здесь НЕ разобрали
Это короткое изложение, рассчитанное на то, чтобы вы понимали кастоди-архитектуру биржи, а не то, чтобы вы завтра сели писать собственный HD-кошелёк. За кадром осталось много важного:
- Функция деривации. BIP-32 использует
HMAC-SHA512с родительским chain-code для получения потомков. Это не magic — это конкретная формула, которую можно (и нужно) понять, если вы собираетесь что-то реализовывать. - Hardened vs non-hardened derivation. Я упомянул штрих и «границу секретности», но механика того, почему именно hardened-узлы не выводятся из xpub, требует отдельного объяснения. Это одна страница формул, но страница, в которой нельзя ошибиться — исторически на этом обжигались реализации.
- Chain code. Помимо 256 битов ключа, каждая нода дерева несёт 256 битов chain-code, который добавляет энтропии в деривацию и защищает от некоторых классов атак. В интерфейсе вы этого не видите, но в xpub/xpriv оно всегда присутствует.
- BIP-39 → BIP-32. Как именно из 24 слов получается тот самый мастер-seed. Это отдельная спецификация с PBKDF2 и опциональной passphrase.
- SLIP-39. Как мнемонику разрезать на несколько Shamir-частей так, чтобы восстановление требовало, скажем, 2-of-3 частей — параллельно тому, что мы обсуждали для подписей в multisig/MPC.
Всё это — дисциплина вечернего чтения, и оно того стоит. Спецификации короткие, формулы арифметические, примеры в BIP-32 приведены прямо в тексте. Если вы собираетесь работать не только с биржей, но и с кошельками вообще — понимание HD-wallets полезно далеко за пределами нашего контекста, потому что это база почти всего, что сейчас живёт в экосистеме.
Подписи: multisig vs MPC
Мы уже несколько раз упомянули «multisig» и «MPC», пора поговорить о них как следует. Вопрос, на который они оба отвечают: как сделать, чтобы ни один человек и ни одна машина не могли в одиночку перевести средства.
Чтобы разговор был предметным, представим конкретную ситуацию. Биржа средней руки держит $120 млн в cold-кошельках. На неё работают три офицера кастоди: Алиса (CTO), Боб (CFO) и Карол (SecOps-lead). Один раз в неделю им нужно перевести $5 млн из cold в warm — чтобы пополнить буфер под ежедневные выводы. Правило операционной политики звучит просто: для любого движения с cold-адреса нужно согласие двух из трёх. Это значит, что ни один из троих в одиночку не может ни украсть средства, ни (что не менее важно) быть принуждённым к переводу под угрозой. Если кто-то заболел или уволился — оставшиеся двое всё ещё могут двигаться, потому что правило «2 из 3», а не «3 из 3».
Это и есть задача, которую решают multisig и MPC. Оба дают одну и ту же операционную гарантию: «ни один человек не может перевести средства в одиночку». Но механизм, которым они это делают, — принципиально разный.
- Правила прозрачны — их проверяет сеть
- Полная независимость подписантов
- Работает с момента изобретения (BIP-11 / P2SH)
- Видно в сети — нарушает приватность
- Дороже: 2–3× размер транзакции
- Нет поддержки там, где нет мультисиг-скриптов
- Неотличимо от single-sig — дешевле и приватнее
- Работает на любой сети, даже без мультисига
- Можно менять набор участников без миграции адресов
- Сложная криптография (GG18 и его наследники)
- Нет on-chain-аудита: кто подписал — видно только в логах биржи
- Почти все реализации — вендорские продукты
| Multisig | MPC | |
|---|---|---|
| Где живёт правило | в скрипте блокчейна | в off-chain-протоколе |
| Размер транзакции | больше обычной | как обычная single-sig |
| Приватность | структура видна всем | нейтральная |
| Аудит | on-chain | только логи вендора |
| Ротация ключей | новый адрес | перешаринг долей |
| Поддержка сетей | зависит от сети | любая сеть с ECDSA/EdDSA |
On-chain multisig — правило записано в сеть
В multisig-схеме само правило «2 из 3» закреплено на уровне блокчейна. Алиса, Боб и Карол генерируют у себя по обычному ключу (каждый — у себя на своей YubiKey или на своём HSM, эти ключи не знают друг о друге). Из трёх публичных ключей собирается один адрес — «2-of-3 multisig address». С точки зрения блокчейна это обычный адрес, просто его скрипт говорит: «потратить можно, только если предъявлены как минимум две подписи из этих трёх публичных ключей». В биткоине это реализовано через P2SH (BIP-11/BIP-16) или P2WSH, в Ethereum — через контракт типа Gnosis Safe, в Solana — через SPL multisig, и так далее.
Как проходит перевод $5 млн? Сервис казначейства составляет незаполненную транзакцию (unsigned tx) и рассылает её Алисе и Бобу. Алиса проверяет её на своём ноутбуке, подписывает своим ключом и возвращает. Боб делает то же самое. Сервис собирает две подписи вместе с незаполненной транзакцией, формирует multisig script, публикует. Карол не участвует — и это нормально, правило «2 из 3» предусматривает её как резерв. Блокчейн видит транзакцию, проверяет: «две из трёх подписей валидны? — да, исполняю».
Что это даёт:
- Правила прозрачны и проверяются сетью, а не сервисом биржи. Аудитор может, не спрашивая биржу, посмотреть в блокчейн и убедиться: да, этот адрес защищён схемой 2-of-3, перевод действительно подписан двумя разными ключами.
- Независимость подписантов. Алиса, Боб и Карол могут держать свои ключи на разных устройствах в разных странах, пользоваться разным программным обеспечением — совместимость обеспечивает сам формат блокчейна.
- Зрелость. Multisig в биткоине существует с 2012 года, за это время через него прошли триллионы долларов, все углы вычищены.
Чем платим:
- Транзакция заметно дороже. В блокчейн идут все участвующие подписи и скрипт, а это в 2–3 раза больше байт, чем у обычного перевода. На сетях с высокими комиссиями это существенно.
- Приватность. Весь мир видит, что этот адрес — multisig 2-of-3, и может отслеживать любые движения. Для средней биржи это полуавтоматический сигнал вида «вот главный cold-кошелёк, вот его структура».
- Поддержка. В биткоине и Ethereum — прекрасно. В более молодых сетях — либо не очень, либо нет вовсе.
Off-chain MPC — правило зашито в криптографию
MPC (Multi-Party Computation), в нашем контексте — threshold signatures, идёт от другой стороны. Вместо того, чтобы писать правило «2 из 3» в блокчейн, оно зашивается прямо в математику подписи. Алиса, Боб и Карол участвуют в специальном протоколе (GG18, CMP, FROST — это разные академические схемы с одной идеей), в результате которого у каждого появляется доля одного-единственного приватного ключа. Ключ как целое никто и никогда не видит: он существует только как «то, что получится, если соединить любые две доли из трёх». В блокчейне появляется обычный single-sig адрес, такой же, как у любого пользовательского кошелька.
Когда приходит время подписать перевод, Алиса и Боб запускают интерактивный протокол подписи (несколько раундов сообщений между их серверами). В конце этого протокола рождается одна валидная ECDSA- или EdDSA-подпись, которую можно послать в сеть. Для блокчейна эта подпись неотличима от подписи обычного одиночного пользователя. Карол в протоколе не участвует — и никто снаружи не узнает ни о ней, ни даже о том, что за адресом стоит коллективная структура.
Что это даёт:
- Цена и приватность как у single-sig. Транзакция в блокчейне выглядит как обычный перевод, никто не видит схему хранения, размер минимальный.
- Универсальность. Работает на любой сети, поддерживающей ECDSA или EdDSA, — а это почти всё, что живёт в индустрии. Для экзотических сетей, где мультисига нет, MPC — единственный практичный путь.
- Гибкость в ротации. Если Карол увольняется, её долю можно «перешарить» внутри MPC-протокола так, чтобы новый набор (Алиса, Боб, Дэн) получил доли того же самого ключа. Адрес на блокчейне не меняется — средства никуда не переезжают. В multisig-мире на такое пришлось бы заводить новый адрес и физически переводить туда всё содержимое.
Чем платим:
- Сложная криптография. GG18 и его наследники — это серьёзная математика, в которой за последние годы находили уязвимости даже в коммерческих реализациях. Если multisig можно собрать на стандартных кирпичиках биткоина, то MPC — это отдельная дисциплина, которой занимается горстка специализированных вендоров (Fireblocks, Copper, ZenGo и так далее).
- Аудит только в логах биржи. Раз на блокчейне ничего не видно, проверить «действительно ли это была 2-of-3 подпись» можно только в логах самого сервиса MPC. Для регулятора это хуже, чем on-chain multisig, где всё читается прямо из сети.
- Замкнутость на вендора. Открытых, широко проверенных реализаций почти нет — в проде используются коммерческие продукты, и с ними биржа связана не меньше, чем с поставщиком HSM.
Как это выглядит на практике
В реальности крупные биржи используют обе техники в разных местах — и решение каждый раз утилитарное, а не идеологическое:
- Cold-хранилища на больших блокчейнах (BTC, ETH) — часто multisig. Регулятору и аудитору проще показать структуру, которую они могут проверить независимо, не заглядывая в код биржи.
- Warm-слой и всё, что живёт на альткоинах без нативного мультисига, — почти всегда MPC. Там, где мультисиг-скриптов нет вовсе, выбора и не остаётся.
- Hot-кошельки — смесь: часть бирж автоматизирует подпись через тот же MPC-вендор, что и warm, часть делает это через HSM c single-sig, часть комбинирует.
Идея здесь не в том, чтобы «определиться раз и навсегда», а в том, чтобы на каждом конкретном cold/warm/hot-слое выбрать подход, у которого профиль ограничений лучше всего сочетается с активами и регуляторными требованиями этого слоя. Это не конкуренты — это инструменты с разным профилем.
Proof of Reserves: доверять или проверять
И вот мы подошли к большому философскому вопросу: как пользователю убедиться, что биржа действительно держит его средства?
На бумаге баланс — это строчка в базе данных. Биржа легко может показать вам «у вас 1 BTC», но в её реальных кошельках может не быть этого BTC — он уже давно улетел на рискованные ставки или «временно одолжен» материнской компании. Инвариант платёжеспособности, который мы подробно разбирали в разделе про леджер, — это проверка, которую биржа делает у себя внутри. Но если сама биржа ему не следует, внутренняя проверка молчит. Значит, нужен способ, которым внешний наблюдатель мог бы убедиться, что инвариант выполняется, не доверяя на слово коду биржи.
Именно на этом сгорела FTX — подробный разбор кейса мы уже сделали в том же разделе про леджер. Для нас здесь важна только одна деталь из той истории: у FTX не было никакой формы внешнего доказательства резервов. Клиентские средства смешивались с торговым капиталом Alameda, и снаружи это было невозможно увидеть, потому что нечего было смотреть — биржа не публиковала ничего, что можно было бы независимо проверить. Именно эту дыру индустрия и начала затыкать сразу после краха.
Инструмент, на котором индустрия сошлась, называется Proof of Reserves. Виталик Бутерин буквально через несколько дней после краха FTX опубликовал статью о том, как CEX могут криптографически доказывать платёжеспособность без раскрытия индивидуальных балансов. Главный инструмент — Merkle-tree.
Как это работает:
- Биржа берёт все обязательства (балансы пользователей), хеширует каждую строку, строит из них Merkle-tree и публикует корень — один хеш.
- Каждому пользователю биржа выдаёт его inclusion proof — цепочку хешей от его листа до корня. Пользователь сам пересчитывает путь и сверяет с опубликованным корнем. Если совпадает — его баланс точно учтён в этом корне.
- Сумма всех листьев — это общие обязательства биржи. Сравнив их с публично доказанными резервами (подписями с on-chain-адресов или SOC-отчётами), можно грубо оценить платёжеспособность.
Важный нюанс: Merkle-PoR показывает только обязательства (liabilities). Чтобы картина была полной, биржа также должна доказать резервы (reserves) — обычно через подписанные сообщения с холодных адресов или через независимого аудитора. Без этой второй половины опубликованный корень превращается в «балансы пользователей на бумаге, и что?». Именно на этом после 2022 года многие биржи поставили акцент — Binance, Kraken, OKX и другие стали публиковать Merkle-корни регулярно, а часть из них — и подписанные резервы.
Ещё немного шрамов индустрии
Коротко — для полноты картины. Каждая из этих историй могла бы быть отдельной главой, но здесь нам достаточно урока.
-
QuadrigaCX (2019). Канадская биржа потеряла доступ к холодным кошелькам после внезапной смерти CEO — единственного человека, владевшего приватниками. Регулятор Ontario Securities Commission позже установил, что холодных кошельков никогда не существовало — это был простейший Ponzi. Урок: bus factor = 1 в кастоди недопустим. Любая серьёзная схема подписи предполагает нескольких участников и документированные процедуры восстановления.
-
WazirX (2024). Индийская биржа потеряла ≈$234,9 млн из Gnosis Safe multisig-кошелька. Атакующие (приписывают Lazarus Group) применили социальную инженерию к одному из подписантов, а в момент подтверждения подменили данные транзакции — подписанты увидели одно, подписали другое. Урок: multisig не спасает от фишинга интерфейса подписи. Даже три независимых подписанта недостаточно, если все они смотрят на одинаково скомпрометированный фронтенд.
Каждая такая история — ещё один пункт, который архитектура кастоди обязана держать в голове. Индустрия учится не по whitepaper'ам, а на собственных провалах — и за каждый такой провал кто-то уже заплатил.
Что запомнить
- Температурная стратификация обязательна. Hot ≈ 2–5%, warm ≈ 10%, cold ≈ 85–90%. Всё остальное — это история Mt. Gox в замедленной съёмке.
- Депозиты зачисляются только после N подтверждений. N зависит от сети и от политики биржи; до порога средства — висят в воздухе, а reorg может их откатить.
- Вывод — это конвейер, не одна кнопка. Риск-скоринг, заморозка, батчинг, HSM-подпись, broadcast, подтверждения, финализация. Каждая стадия может увеличить задержку на часы.
- HD-кошельки (BIP-32/44) позволяют иметь миллионы пользовательских адресов из одного мастер-seed. Сканер работает с
xpub, приватники — в холоде. - Multisig и MPC решают одну задачу на разных уровнях. Multisig — в блокчейне, MPC — в криптографии. Крупные биржи используют обе.
- Proof of Reserves после FTX — это обязательный минимум. Merkle-tree по обязательствам + подписанные сообщения по резервам = минимальная внешняя проверяемость.
- Все крупные катастрофы — про одно и то же: слишком много денег в слишком доступном месте, или слишком мало людей с ключами, или ноль независимой проверки снаружи. Дисциплина кастоди — это не паранойя, это цена, которую индустрия заплатила за каждый из этих случаев.
Дополнительное чтение
- BIP-32 — HD Wallets. bitcoin/bips/bip-0032.mediawiki — оригинальная спецификация иерархических детерминированных кошельков.
- BIP-44 — Multi-Account Hierarchy. bitcoin/bips/bip-0044.mediawiki — стандарт пути
m/44'/coin'/account'/change/index. - Виталик Бутерин, «Having a safe CEX: proof of solvency and beyond». vitalik.eth.limo — ключевая статья про PoR, опубликованная через несколько дней после FTX.
- GG18 — Fast Multiparty Threshold ECDSA. eprint.iacr.org/2019/114.pdf — академический фундамент большинства современных MPC-реализаций.
- Fireblocks Developer Portal. developers.fireblocks.com — документация одного из ведущих MPC-кастоди-вендоров.
- Отчёт OSC по QuadrigaCX. osc.gov.on.ca — подробный разбор того, как отсутствие кастоди-дисциплины уничтожило биржу.