Что такое Provably Fair и как проверить честность игры
Что такое Provably Fair (PF)
Provably Fair — это протокол, позволяющий криптографически проверить, что результат раунда был случайным и не мог быть подменён оператором после ставки.
Идея: сначала публикуется коммит (хэш скрытого server seed), затем после ставки раскрывается ревил (сам server seed), и любой может сверить хэш и воспроизвести RNG, учитывая client seed игрока и идентификаторы раунда.
Базовый протокол: commit → bet → reveal
1. Commit: до начала раундов сервер генерирует случайный `server_seed` и публикует его хэш:
commit = SHA-256(server_seed salt) // или Keccak-256
Коммит можно вывести в историю/блокчейн/журнал.
2. Ставка: игрок выбирает или подтверждает свой `client_seed` (из UI или собственный), отправляет ставку с:
client_seed, roundId, nonce
3. Reveal: после закрытия ставок сервер раскрывает `server_seed` (и `salt`, если был), чтобы все могли проверить:
SHA-256(server_seed salt) == commit // проверка целостности
4. RNG: число случайности детерминировано и воспроизводимо:
rng = HMAC-SHA256(key=server_seed, msg=client_seed roundId nonce)
// или rng = SHA-256(server_seed client_seed roundId nonce)
5. Маппинг в исход: преобразуем `rng` в диапазон игры без смещения (см. ниже).
Как получить число без смещения (bias-free)
Неправильно брать `rng % N` — это даёт модульное смещение, если 2^k не кратно N. Правильно — rejection sampling:pseudo
// rng_bytes = 32 байта хэша → uint256 x = uint256(rng_bytes)
limit = floor(2^256 / N) N while x >= limit:
rng_bytes = SHA-256(rng_bytes) // «перемешать» ещё раз детерминированно x = uint256(rng_bytes)
result = x % N
Так получаем равномерное распределение по N исходам (ячейки рулетки, символы барабана и т. п.).
Мини-пример (пошаговая верификация игроком)
Предположим:
server_seed = "b2c6...e9" // раскрыт после раунда (hex/utf8)
client_seed = "my-client-seed" // выбран мной roundId = "R-2025-10-17-001"
nonce = 42 commit = "c9a1...f3" // опубл. заранее
1) Проверить коммит
Посчитать `SHA-256(server_seed)` и убедиться, что совпадает с `commit`.
2) Детерминированный RNG
Посчитать:
rng = HMAC-SHA256(key=server_seed, msg= client_seed ":" roundId ":" nonce)
3) Преобразование в исход
Для рулетки (37 чисел) → N=37, применить rejection sampling и взять `x % 37`.
Для слота: использовать несколько порций RNG для определения барабанов/символов согласно таблице распределений.
4) Сверить с результатом в истории
Площадка должна показывать те же входные, которые использовались в расчёте: `server_seed`, `client_seed`, `roundId`, `nonce`, `hashAlgo`, `rngAlgo`, `mappingVersion`.
Альтернатива/усиление: VRF (Verifiable Random Function)
Вместо коммита оператор может (или дополнительно) использовать VRF:1. Смарт-контракт или публичный реестр запрашивает у провайдера `VRF(seed)`.
2. Публикуется `(random, proof)`.
3. Любой может проверить `proof` той же публичной ключевой парой VRF.
4. Далее — те же шаги маппинга RNG в исход.
Плюсы: меньше доверия к оператору. Минусы: зависимость от VRF-провайдера/цепи и возможная стоимость.
Как казино должно внедрять PF корректно
Договор (контракт данных PF)
Поля в истории раунда:- `serverSeedHash`, `serverSeedReveal`, `clientSeed`, `roundId`, `nonce`, `hashAlgo`, `rngAlgo`, `mappingVer`, `proofUrl` (опц.), `calcVer`.
- Значения — в WORM-хранилище (immutable), со штампами времени (UTC).
Генерация сидов
`server_seed` генерируется криптостойким PRNG (OS CSPRNG/HSM).
Сиды никогда не должны повторяться между сериями (ротация).
`client_seed` — выбирается игроком или генерируется на клиенте и подтверждается.
Публикация коммитов
Коммиты доступны до ставок (история, RSS, on-chain-якорь).
Для лотов можно использовать меркли-дерево коммитов с ежедневной публикацией корня.
Раскрытие (reveal)
Перед публикацией результата `server_seed` раскрывается и логируется.
Для серии раундов на одном сидe — раскрытие после конца серии (указать политику заранее).
Прозрачный маппинг
Версия алгоритма маппинга (`mappingVer`) фиксируется.
Любое изменение (`mappingVer`/`rngAlgo`) — только с анонсом и новой серией коммитов.
Аудит и споры
Сырые входы + запись вычислений сохраняются; при споре генерируется отчёт: входы → RNG → mapping → исход.
Стримы/Live: хранить хэш-якоря событий CV/RFID, видео — в WORM.
Как игроку проверить честность (чек-лист)
1. Откройте историю раунда и скопируйте: `serverSeedReveal`, `clientSeed`, `roundId`, `nonce`, `hashAlgo`, `rngAlgo`, `mappingVer`.
2. Посчитайте хэш `serverSeedReveal` и сравните с `serverSeedHash`.
3. Посчитайте RNG по указанному алгоритму (HMAC/Hash + входы).
4. Примените «безсмещённый» маппинг (rejection sampling) к числу исходов.
5. Убедитесь, что результат совпадает с показанным.
6. Если заявлена VRF — проверьте `proof` (кнопка «Verify» или независимый скрипт/блок-эксплорер).
Типовые ошибки (анти-паттерны)
`rng % N` без rejection sampling → смещённые вероятности.
Скрытый или меняющийся `client_seed` (генерируется сервером без участия игрока).
Перегенерация `server_seed` после ставки (коммит меняется задним числом).
Непрозрачные изменения алгоритмов без версии/публикации.
Повтор сидов между сериями.
Отсутствие WORM/штампов времени — нельзя доказать порядок событий.
Смешение PF и бизнес-логики (например, бонус применён так, что меняет пространство исходов, но это не описано в `mappingVer`).
FAQ (коротко)
Можно ли проверить слоты, а не только рулетку?
Да. PF применяют к последовательности выборов (например, индекс символа на барабане). Важно, чтобы таблицы вероятностей и порядок чтения RNG были задокументированы.
А если я ввёл свой `client_seed`, оператор всё равно может «подобрать» `server_seed`?
Нет, если коммит был опубликован до ставки. Он фиксирует `server_seed` и не даёт заменить его задним числом.
Почему иногда раскрывают сиды пакетно?
Чтобы не было возможности «перебирать» сид в серии. Это допустимо, если коммит опубликован заранее, а политика раскрытия — прозрачна.
Мини-референс форматов
Хэши: SHA-256 или Keccak-256.
RNG: HMAC-SHA256 (серверный сид как ключ) либо SHA-256 конкатенации.
Идентификаторы: `roundId` (UTC-штамп + игра + инкремент), `nonce` (счётчик ставок в серии).
Версии: `rngAlgo=HMAC-SHA256@1`, `mappingVer=roulette.v2`, `calcVer=wallet-7.2`.
Чек-лист внедрения PF для оператора
Криптография и сиды
- CSPRNG/HSM; уникальные `server_seed`, документированная ротация.
- `client_seed` — управляемый игроком, сохраняется в истории.
Публикации и хранение
- Коммиты до ставок, доступ к истории/каналу публикаций/якорю.
- WORM-хранилище, UTC-штампы, меркли-батчи для масштабов.
Алгоритмы
- RNG и mapping без смещения; версионирование `rngAlgo/mappingVer`.
- Скрипт/страница «Проверить честность» (open-source желателен).
Live и гибрид
- Хэш-якоря CV/RFID/фаз раунда, журнал «когда закрыли окно ставок».
- Процедуры спора (отчёт входов→исход, ссылки на коммиты/VRF).
Безопасность и аудит
- Независимый аудит протокола PF, баг-баунти.
- Логи решений неизменяемы; регулярные тесты воспроизведения.
Provably Fair превращает «поверьте нам» в «проверьте сами». С коммит/ревил или VRF, детерминированным RNG и корректным маппингом без смещения любой раунд становится воспроизводимым и проверяемым. Для игрока — это прозрачность и доверие. Для оператора — меньше споров, сильнее бренд и соответствие требованиям регуляторов. Главное — дисциплина: публиковать коммиты заранее, фиксировать версии алгоритмов, хранить доказательства неизменно и давать пользователю простой инструмент проверки.