Пошаговое руководство по курсу
Различайте доказательство из лабораторной и данные развёртывания. Локальные упражнения ECVRF, VDF и лотерея выполняются без оплаты. В витрине лотереи сначала проверьте окружение и доказательства розыгрыша. UNI использует имитацию блокчейна. Транзакцию Base проверяйте в Base. Документированный вход в LIVE — бесплатное место за работу через
enterFromWork, платные билеты выключены.
Для кого: разработчики, которым нужна случайность, проверяемая самим игроком лотереи — до подключения
lottery/на Base. Языки:COURSE_LANG=en|ru|es· строки UI вi18n/· этот гайд на русском. English: step-by-step.md · Español: step-by-step.es.md
Зачем этот курс
Большинство лотерей и «случайных» розыгрышей доверяют оператору, который может тихо перекрутить невыгодный результат. Курс показывает криптографию, которая убирает это доверие: верифицируемый chaos-розыгрыш, функцию проверяемой задержки (VDF), доказывающую затраченную работу, доказательство ECVRF, проверяемое офлайн всего из 80 байт, и time-lock RSW, скрывающий значение до тех пор, пока его не раскроет доказуемая работа. Затем вы соберёте смещённую лотерею, сломаете её и почините розыгрышем, который оператор не может перебирать — ровно тот паттерн, что потребляют контракты AIMarket lottery/ на Base.
Каждая лаба обращается к реальному оракулу AIMarket — Platon, Chronos, Sortes, Aestus — запущенному локально, а не к моку. Каждая печатает блок trace, чтобы верифицируемый артефакт (доказательство, beta, puzzle, вектор VDF) можно было изучить, а не принимать на веру.
Содержание
- Выбор трека
- Установка (10 минут)
- M1 — Chaos VRF с Platon
- M2 — VDF-время с Chronos
- M3 — ECVRF и Sortes
- M4 — Time-lock RSW с Aestus
- M5 — Commit–reveal и атаки смещения
- M6 — Проверка on-chain
- Чтение трейса (в каждой лабе)
- Упражнения и сертификат
- Мост: от курса к лотерее на Base
- Чеклист самопроверки
- Типичные проблемы
Выбор трека
| Трек | Модули | Время | Оракулы |
|---|---|---|---|
| Базовый | M1 → M2 → M3 → M4 | ~2 ч | Platon, Chronos, Sortes, Aestus (локально) |
| Экономика | Базовый + M5 | +30 мин | Sortes (честная vs смещённая лотерея) |
| Продвинутый | Экономика + M6 | +30 мин | Chronos + Sortes → вектор для тестнета Base |
После каждой лабы смотрите блок trace — это её аудит-лог.
Установка (10 минут)
Шаг 1 — Клон и установка
Точные команды быстрого старта (обратите внимание на extra [oracles,dev] — oracles тянет Platon/Chronos/Sortes/Aestus, dev — pytest):
git clone https://github.com/alexar76/aimarket-courses.git
cd aimarket-courses/verifiable-randomness-course
pip install -e ".[oracles,dev]"
Из монорепы aicom (рекомендуется для контрибьюторов): пакеты оракулов подключаются автоматически по соседним путям в oracles/ — courselib/oracle_paths.py поднимается до корня монорепы и добавляет oracles/oracles/{chronos,sortes,aestus} и oracles/oracles/platon/backend в sys.path. Кроме numpy для Platon, ничего ставить не нужно.
cd courses/verifiable-randomness-course
pip install -e ".[oracles,dev]"
Шаг 2 — Тесты
pytest -q
Ожидается: все тесты зелёные (паритет i18n en/ru/es, хелперы случайности, проверки упражнений).
Шаг 3 — Язык интерфейса лаб (опционально)
Строки UI (заголовки, метки доказательство/проверка/трейс, названия билетов) берутся из i18n/{en,ru,es,fr,zh}.json. Переключение через COURSE_LANG:
export COURSE_LANG=ru # или es, по умолчанию en
python labs/lab01_platon_chaos.py
Шаг 4 — Google Colab
- Откройте сайт курса → Open in Colab на любой лабе.
- Выполните setup-ячейку (clone +
pip install -e ".[oracles,dev]"). - При необходимости в setup-ячейке:
os.environ["COURSE_LANG"] = "ru". - Запустите ячейку лабы.
M1 — Chaos VRF с Platon
Концепция: непредсказуемая случайность от верифицируемого chaos-оракула — chaos-state + client seed + энтропия ОС, связанные подписью Ed25519.
Лаба: labs/lab01_platon_chaos.py · ~15 мин · нужен numpy + Platon
Шаги
- Прочитайте docstring в начале
labs/lab01_platon_chaos.py(отрасль: лотереи, гейминг). python labs/lab01_platon_chaos.py- В выводе: схема
доказательство, первые байты розыгрыша, результатпроверка. courselib/randomness.py→chaos_draw(): временныйSigner, chaos-state,draw_randomness(...), затемverify_randomness(...).
Ожидаемый вывод
proof: scheme=platon-chaos-vrf/v1, подписанный розыгрыш 32 байта,verify: True- блок
traceс событиемchaos_draw(verified=True, bytes=32)
Самопроверка
- [ ] Объясняете, почему client seed + подпись делают розыгрыш непредсказуемым
- [ ] Видите 32 байта и
verify: Trueпротив публичного ключа
M2 — VDF-время с Chronos
Концепция: Wesolowski VDF доказывает затраченную последовательную работу в группе неизвестного порядка RSA-2048 — доказательство затраченной работы, а не доверие к системным часам.
Лаба: labs/lab02_chronos_vdf.py · ~20 мин · нужен M1
Шаги
python labs/lab02_chronos_vdf.py- Строка
доказательство: proofpiи простоеl;verify: True. - Демо подделки: лаба вызывает
vdf.verify(g, y+1, …)на испорченном выходе — печатаетFalse. courselib/randomness.py→vdf_eval():hash_to_group→evaluate→prove→verify. Используетсяdifficulty=700(~700 возведений в квадрат) — считается за секунды.
Ожидаемый вывод
proof: pi=…… l=<простое>,verify: True,проверка подделанного VDF: Falsetraceс событиямиvdf_evalиtamper_check
Самопроверка
- [ ] Формулируете, что VDF доказывает (последовательную работу) и что не доказывает (реальное время)
- [ ] Видели отказ проверки на подделанном выходе
M3 — ECVRF и Sortes
Концепция: доказательство ECVRF по RFC 9381. Для фиксированной пары (публичный ключ, alpha) существует ровно одна валидная beta — оператор не может перебирать выгодный выход. Доказательство — 80 байт и проверяется офлайн, без повторного обращения к оракулу.
Лаба: labs/lab03_sortes_ecvrf.py · ~20 мин · нужен M1
Шаги
python labs/lab03_sortes_ecvrf.py- Убедитесь, что доказательство ровно 80 байт (
80 bytes = <hex>…). - Отметьте
beta(верифицируемый случайный выход) иverify: True. courselib/randomness.py→ecvrf_draw():sk_to_pk→prove(sk, alpha)→verify(pk, alpha, pi).
Ожидаемый вывод
proof: 80 bytes = <hex>…,result: beta=<hex>…,verify: Truetraceс событиемecvrf(proof_len=80, verified=True)
Самопроверка
- [ ] Объясняете «одна beta на (pk, alpha)» и почему это блокирует перебор
- [ ] Проверили, что доказательство 80 байт (число офлайн-проверки из тэглайна)
M4 — Time-lock RSW с Aestus
Концепция: головоломка time-lock RSW. Запечатайте значение сейчас; открыть его можно только после T последовательных возведений в квадрат — зашифруйте сейчас, расшифруйте после доказуемой задержки. Кирпич для запечатанных ставок и commit-reveal, где никто не должен подглядывать раньше времени.
Лаба: labs/lab04_aestus_timelock.py · ~20 мин · нужен M2
Шаги
python labs/lab04_aestus_timelock.py- Цикл seal → open:
T=350возведений, затем открытый payload иverify: True. courselib/randomness.py→timelock_seal():rsw.seal(message, T=...)→rsw.open_puzzle(puzzle);message_matchподтверждает целостность открытого текста.
Ожидаемый вывод
proof: T=350 squarings,result: <открытый payload>,verify: Truetraceс событиемtimelock(T=350, opened=True)
Самопроверка
- [ ] Объясняете, почему time-lock скрывает значение без доверенной третьей стороны
- [ ] Видели восстановление запечатанного сообщения после
Tвозведений
M5 — Commit–reveal и атаки смещения
Концепция: ключевой модуль. Соберите лотерею, которую нечестный оператор может перебирать, покажите смещение, затем замените розыгрыш на Sortes ECVRF, который оператор перебрать не может.
Лаба: labs/lab05_commit_reveal.py · ~25 мин · трек: экономика · нужен M3
Шаги
python labs/lab05_commit_reveal.py- Сравните билеты:
смещённый билетvsчестный VRF-билет. Строкаverify VRF: Trueдоказывает, что честный розыгрыш несёт верифицируемое доказательство. - Прочитайте аудит-заметку: «Честный розыгрыш привязывает одну beta к каждому seed — оператор не может перебирать.»
courselib/randomness.py→BiasedLottery(до 200 попыток перебораoperator_secret|player_seed|attemptради джекпота) vsFairLottery(один розыгрыш ECVRF → один билет, перебор невозможен).
Ожидаемый вывод
смещённый билет: <n>ичестный VRF-билет: <n>,verify VRF: True, строка аудит-заметкиtraceс событиямиcommitиdraw(vrf_ok=True)
Самопроверка
- [ ] Описываете атаку перебором, которую делает
BiasedLottery - [ ] Объясняете, почему
FairLottery(одна beta на seed) к ней невосприимчива
M6 — Проверка on-chain
Концепция: упакуйте доказательства для on-chain-потребителя — вектор Wesolowski VDF под Solidity-верификатор плюс 32-байтовое слово лотереи из beta Sortes ECVRF.
Лаба: labs/lab06_onchain_consumer.py · ~20 мин · трек: продвинутый · нужны M2, M3
Шаги
python labs/lab06_onchain_consumer.py- Строка
протокол: wesolowski-vdf,verify: Trueи 32-байтовоеслово лотереи: 0x…. courselib/randomness.py→onchain_vdf_vector()(отдаётscheme/seed/difficulty/y/pi/l/validстроками под верификатор) иlottery_word_from_vrf()(первые 32 байта beta ECVRF).- Мост: лаба печатает deploy-заметку со ссылкой на lottery/docs/deployments-base.md — живой верификатор
ChronosVDF.solна Base.
Ожидаемый вывод
protocol: wesolowski-vdf,verify: True,слово лотереи: 0x<hex>…, строка deploy-заметкиtraceс событиямиonchain_vdfиlottery_word
Самопроверка
- [ ] Называете два артефакта для on-chain-потребителя (вектор VDF + слово VRF)
- [ ] Знаете, где найти доки по деплою на Base
Чтение трейса (в каждой лабе)
Концепция: каждая лаба пишет небольшой Trace (см. courselib/trace.py), чтобы поведение агента/оракула можно было изучить.
Шаги (после каждой лабы)
- Найдите блок
trace (<n> событий):внизу вывода. - Прочитайте каждое событие —
kindплюс залогированные поля (chaos_draw→verified, bytes;vdf_eval→difficulty, valid;tamper_check→valid=False). - Сопоставьте каждое событие со строкой stdout выше. Трейс — это «лог юнит-теста» верифицируемой случайности.
Самопроверка
- [ ] Показываете событие, доказывающее, что розыгрыш прошёл проверку
- [ ] В M2 находите событие
tamper_checkсоvalid=False
Упражнения и сертификат
После лаб запустите DIY-проверки. У каждого модуля своё упражнение в courselib/exercises.py (M2 подделывает VDF и проверяет, что verify падает; M3 проверяет ровно 80 байт; M5 — что честный розыгрыш проходит проверку):
python labs/run_exercises.py # все шесть, ✓/✗ по модулям
python labs/run_exercises.py --module m3 # проверка одного модуля
Когда все шесть зелёные — выпустите сертификат:
python labs/run_exercises.py --certificate "Иван Петров" --lang ru # или --lang en / es
Создаётся certificate.html — откройте в браузере и Print → Save as PDF. ID удостоверения детерминированно выводится из имени + даты выпуска (courselib/certificate.py). Сертификат блокируется до прохождения упражнений, если не передать --skip-check.
Мост: от курса к лотерее на Base
Цель: те же доказательства, что вы получили локально, проверяют контракты AIMarket lottery/ на Base.
| Курс | Лотерея на Base |
|---|---|
| M2 вектор Chronos VDF | верификатор Wesolowski ChronosVDF.sol |
| M3 beta Sortes ECVRF | 32-байтовое слово лотереи (M6 lottery_word_from_vrf) |
| M5 честный vs смещённый розыгрыш | почему потребитель берёт VRF, а не доверенный маяк |
M6 onchain_vdf_vector() |
тот самый вектор {y, pi, l} для верификатора |
Адреса деплоя и Solidity-верификатор — в lottery/docs/deployments-base.md.
Чеклист самопроверки
Базовый трек:
- [ ] lab01–lab04 локально (и в Colab) на EN, RU, ES
- [ ] Объясняете chaos VRF, VDF, ECVRF и time-lock в одно предложение каждый
- [ ] Показываете отказ проверки на подделанном VDF (M2)
- [ ] Формулируете, почему 80-байтовое ECVRF проверяется офлайн (M3)
Экономика + продвинутый:
- [ ] lab05 + атака перебором и фикс через VRF
- [ ] lab06 + вектор VDF и слово лотереи под Base
- [ ]
pytest -qзелёный иpython labs/run_exercises.py— все ✓
Типичные проблемы
| Проблема | Решение |
|---|---|
No module named 'chronos' |
pip install -e ".[oracles]" или запуск из монорепы aicom |
No module named 'oracle_core' |
oracles/core должен быть на пути — авто в монорепе; тянется [oracles] для Sortes/Platon |
Oracle package '…' not installed |
вне монорепы и без extra — поставьте .[oracles] или клонируйте рядом с oracles/ |
| Сбой импорта Platon | поставьте numpy; проверьте oracles/oracles/platon/backend |
| Медленная VDF-лаба | лабы используют ~700 возведений (M2) / T=350 (M4) — снижайте сложность только в своём упражнении |
| Пустые строки RU/ES | export COURSE_LANG=ru|es; ключи i18n/ru.json должны совпадать с i18n/en.json |
Ошибка i18n в pytest |
добавьте недостающий ключ во все три каталога (en/ru/es) |
| Старый код в Colab | перезапустите setup-ячейку; зафиксируйте ветку main |
Пересборка сайта и ноутбуков
После правок лаб или i18n:
python3 scripts/build_course_assets.py
Гайды в docs/ правятся вручную — сначала EN, затем зеркала RU/ES.