Блокчейн
VRF и случайность в блокчейне
В 2018 году лотерейный контракт FOMO3D на Ethereum заморозил 10,469 ETH (тогда ~3 млн). Атакующий забил сеть транзакциями, чтобы именно его блок оказался последним перед дедлайном, и забрал весь джекпот. Контракт использовал block.timestamp как источник случайности. Проблема была не в баге кода, а в фундаментальном вопросе: откуда в детерминированной системе, где каждый узел должен получить одинаковый результат, может взяться настоящая случайность?
- **Algorand** - каждый валидатор вычисляет VRF локально, чтобы определить, станет ли он proposer блока. Никто не знает лидера до момента публикации блока
- **Ethereum Beacon Chain** - RANDAO (XOR BLS-подписей всех proposer-ов эпохи) определяет распределение валидаторов по комитетам и слотам
- **Chainlink VRF** - используется в сотнях DeFi-протоколов и NFT-проектов для проверяемой генерации случайных чисел on-chain
Предварительные знания
Зачем блокчейну случайность
Блокчейну нужна **случайность** для множества задач: выбор валидатора, который предложит следующий блок, распределение наград в лотерейных контрактах, генерация случайных атрибутов NFT. Но в детерминированной среде смарт-контрактов это нетривиальная задача.
**Проблема:** блокчейн - это **детерминированная** реплицированная машина. Каждый узел должен прийти к одинаковому результату, исполняя одинаковый код. Откуда взять случайное число, если все должны получить одно и то же?
**Наивные подходы не работают:** - `block.timestamp` - майнер может сдвинуть временную метку на несколько секунд - `block.difficulty` - предсказуемо, медленно меняется - `blockhash(block.number - 1)` - майнер видит хеш блока *до* публикации и может отказаться от блока, если результат ему не выгоден
Атака на SmartBillions (2017)
Реальный случай эксплуатации предсказуемой случайности
Лотерея SmartBillions на Ethereum использовала blockhash как источник случайности. Атакующий: 1. Развернул контракт-эксплоит в том же блоке 2. Контракт вычислил blockhash до вызова лотереи 3. Отправил ставку только при выигрышном результате 4. Украл 400 ETH за несколько транзакций Причина: blockhash доступен ВСЕМ контрактам в блоке, а значит, предсказуем в момент исполнения.
Итого, нам нужен механизм случайности, который обладает тремя свойствами: **(1)** непредсказуемость до раскрытия, **(2)** проверяемость после раскрытия, **(3)** устойчивость к манипуляциям одним участником.
Почему использование blockhash как источника случайности в смарт-контракте опасно?
VRF: доказуемая псевдослучайность
**Verifiable Random Function (VRF)** - криптографический примитив, который решает проблему случайности элегантно: владелец секретного ключа генерирует случайное число, а *любой* может проверить, что оно было вычислено корректно, используя публичный ключ.
VRF принимает **секретный ключ** `sk` и **входное значение** `x`, а возвращает два значения: - **output** - псевдослучайное число, неотличимое от случайного без знания `sk` - **proof** - криптографическое доказательство, что output вычислен корректно
**VRF vs обычная подпись:** Обычная подпись доказывает авторство сообщения. VRF делает больше - она **детерминированно генерирует** псевдослучайное число из входа и доказывает, что автор не мог выбрать другой результат. Для одного `(sk, input)` существует ровно один `output`.
Algorand: лотерея валидаторов через VRF
Как Algorand использует VRF для выбора block proposer
В каждом раунде Algorand каждый валидатор локально вычисляет: (output, proof) = VRF(sk_i, round_seed || round_number) Если output < threshold (порог), валидатор «выиграл» право предложить блок. Он публикует (block, proof). Другие узлы проверяют: VRF.verify(pk_i, round_seed || round_number, output, proof) Почему это безопасно: • Никто не знает заранее, кто станет proposer (output непредсказуем без sk) • Proposer не может «подкрутить» результат (output детерминирован для данного sk и input) • Любой может проверить легитимность (proof верифицируется публичным ключом)
VRF построена на тех же **эллиптических кривых**, что и цифровые подписи. В основе - операция умножения точки кривой на скаляр, которая вычислительно необратима (задача дискретного логарифма на эллиптических кривых, ECDLP).
Что гарантирует proof в VRF?
Randomness Beacons: источники случайности
VRF решает проблему случайности для одного участника. Но что если нам нужна **общая**, **публичная** случайность, которую никто в одиночку не контролирует? Для этого существуют **randomness beacons** - протоколы, генерирующие публичные случайные числа через коллективное участие.
**RANDAO** - механизм, используемый в Ethereum (Beacon Chain). Это схема **commit-reveal** с участием множества валидаторов:
В Ethereum PoS RANDAO работает проще: каждый proposer блока **обязан** раскрыть свой `RANDAO reveal` (BLS-подпись текущей эпохи). Протокол XOR-ит все раскрытия за эпоху (32 слота), формируя `randao_mix` - общий источник случайности для следующей эпохи.
**drand (Distributed Randomness Beacon):** Проект **League of Entropy** - коалиция организаций (Cloudflare, Protocol Labs, EPFL и др.), которые совместно генерируют случайные числа каждые 30 секунд. Основан на **threshold BLS подписях**: каждый участник подписывает раунд своей долей ключа. Любые `t` из `n` подписей агрегируются в одну - она и становится случайным числом. drand публично верифицируем и используется в **Filecoin** для выбора лидера.
Chainlink VRF: случайность для смарт-контрактов
Как DeFi и NFT проекты получают проверяемую случайность
Chainlink VRF - oracle-сервис для on-chain случайности: 1. Контракт отправляет запрос на случайное число → requestRandomWords(keyHash, subId, confirmations, ...) 2. Chainlink node получает seed из блокчейна → seed = keccak256(keyHash, requestId, blockHash) 3. Node вычисляет VRF → (output, proof) = VRF(sk_node, seed) 4. Node отправляет (output, proof) обратно в контракт 5. On-chain координатор верифицирует proof → VRF.verify(pk_node, seed, output, proof) == true 6. Контракт получает гарантированно случайное число Используется в: • Axie Infinity - генерация атрибутов персонажей • PoolTogether - no-loss лотерея • NBA Top Shot - определение содержимого паков
Как RANDAO в Ethereum генерирует общую случайность для эпохи?
Устойчивость к смещению: VDF и threshold
Commit-reveal схемы вроде RANDAO имеют фундаментальную уязвимость: **last-revealer attack**. Последний участник, раскрывающий свой секрет, уже видит все остальные раскрытия. Он может **вычислить финальный результат** и решить - раскрывать свой секрет или нет.
Для борьбы с last-revealer attack разработано несколько подходов. Рассмотрим два ключевых: **VDF** и **threshold randomness**.
**VDF (Verifiable Delay Function)** - функция, которая: 1. **Требует строго T последовательных шагов** для вычисления (нельзя ускорить параллелизмом) 2. **Быстро верифицируется** (проверка намного быстрее вычисления) Идея: после того как все секреты собраны, результат прогоняется через VDF. Задержка выбирается так, чтобы VDF **не успевала завершиться** до дедлайна раскрытия. Последний участник не может вычислить финальный результат заранее - у него просто нет на это времени.
**Threshold randomness** - альтернативный подход: группа из `n` участников создаёт случайное число так, что **любые `t` из `n`** могут его восстановить, но `t-1` не получат никакой информации. Основан на **пороговых BLS-подписях** и **Shamir Secret Sharing**.
Threshold BLS в drand
Как drand решает проблему last-revealer
drand использует threshold BLS (t-of-n): • n = 20 участников (Cloudflare, EPFL, и др.) • t = 11 (порог - нужны подписи 11 из 20) Каждые 30 секунд: 1. Все участники подписывают номер раунда своей долей ключа 2. Как только 11 подписей собрано - они агрегируются 3. Агрегированная подпись = случайное число Почему нет last-revealer проблемы: • 11-й подписант НЕ видит финального результата до агрегации • Каждая доля ключа бесполезна без остальных 10 • Результат определяется ВСЕМИ долями, а не последней DKG (Distributed Key Generation) гарантирует, что никто не знает полный секретный ключ - только свою долю.
**Сравнение подходов:**
| RANDAO | VDF + RANDAO | Threshold BLS | |
|---|---|---|---|
| Last-revealer | Уязвим (1 бит) | Защищён (задержка) | Защищён (порог) |
| Доступность | Работает если 1+ proposer онлайн | Требует VDF hardware | Нужно t из n онлайн |
| Используется в | Ethereum PoS | Ethereum (планируется) | drand, Filecoin |
| Сложность | Низкая | Высокая (ASIC для VDF) | Средняя (DKG) |
Хеш блока - хороший источник случайности, потому что он непредсказуем и выглядит случайным
Хеш блока **выглядит** случайным, но **не является** безопасным источником случайности. Майнер/валидатор контролирует содержимое блока и может перебирать варианты, пока хеш не станет выгодным. Безопасная on-chain случайность требует криптографических гарантий - VRF (доказательство корректности), commit-reveal (разделение знания), или threshold-схем (распределение доверия).
Ключевые идеи
- **Наивная случайность опасна:** `blockhash`, `block.timestamp` и подобные on-chain значения предсказуемы для майнера/валидатора - именно так был атакован FOMO3D из нашего вступления
- **VRF** = *детерминированная* псевдослучайная функция + *доказательство* корректности. Для одного `(sk, input)` существует ровно один `output`, и `proof` позволяет любому это проверить
- **Randomness beacons** (RANDAO, drand, Chainlink VRF) решают проблему *общей* случайности через коллективное участие - если хотя бы один участник честен, результат непредсказуем
- **Last-revealer attack** - фундаментальная уязвимость commit-reveal схем. **VDF** решает её через гарантированную задержку вычисления, **threshold BLS** - через пороговую агрегацию, где ни один участник не видит результата до достижения порога
Связанные темы
VRF и случайность в блокчейне опираются на криптографию эллиптических кривых и применяются в консенсус-протоколах:
- Эллиптические кривые (ECC) — VRF построена на операциях с точками эллиптических кривых - умножение точки на скаляр (sk) является необратимой основой безопасности
- Proof of Stake — VRF используется для честного выбора валидатора (proposer selection) в PoS-протоколах - Algorand, Cardano (Ouroboros Praos)
- Gasper (Ethereum PoS) — RANDAO mix используется в Gasper для перемешивания валидаторов по комитетам каждую эпоху
Вопросы для размышления
- Если VDF требует специализированного ASIC для вычисления, не создаёт ли это новую форму централизации - аналогичную ASIC-майнингу в PoW?
- RANDAO в Ethereum даёт last proposer-у эпохи 1 бит влияния. При каких условиях экономическая выгода от этого бита превысит штраф за пропуск слота?
- Можно ли построить полностью trustless randomness beacon без предположения о существовании хотя бы одного честного участника?
Связанные уроки
- bc-07-ecc — VRF construction is based on elliptic curve operations; ECC is prerequisite
- bc-06-digital-signatures — VRF output is accompanied by a proof similar to a signature; signature concepts required
- bc-15-pos — Many PoS protocols (Algorand, Cardano) use VRF for leader election; VRF is the core building block
- bc-08-commitment — VRF provides a commitment to randomness with a proof of correct evaluation
- crypto-19-hash-functions