Доказуемая честность
Исход каждой игры фиксируется до ставки и пересчитывается кем угодно — нам не нужно верить на слово.
Как это работает
В обычном казино вы видите поворот карты, бросок кубика или вращение рулетки. В онлайн-игре это происходит внутри программы — и проверять приходится программу.
Перед ставкой сервер публикует SHA-256-хеш своего секретного сида. Изменить сид задним числом невозможно: хеш это выдаст. После смены пары сидов старый сид раскрывается — и любой бросок, сделанный этой парой, пересчитывается по формуле ниже.
Комиссия площадки — 1%. Выплата считается как ставка × 99 ÷ шанс в процентах, то есть игроку возвращается 99% математического ожидания. Это единственное, чем игра отличается от честной монетки; других удержаний нет.
Сиды
Пара сидов — ваш и наш. Серверный мы создаём случайно и сразу показываем его хеш: сам сид остаётся секретом до смены пары, иначе будущие броски были бы известны заранее. Клиентский вы задаёте сами, и без него бросок не посчитать — исход зависит от обеих сторон.
Третье слагаемое — nonce, номер ставки в текущей паре. Он растёт на единицу с каждой игрой, поэтому два броска одной парой не могут совпасть по входным данным.
Как получается число
Серверный сид, клиентский сид и nonce сворачиваются в HMAC-SHA512. Полученную строку из 128 hex-символов читаем окнами по пять: первое же число, меньшее 1 000 000, делим по модулю 10 000 — получается бросок от 0 до 9999, то есть от 0.00 до 99.99.
Порог отсечения нужен ради честности: окно из пяти hex-символов даёт числа до 1 048 575, а этот диапазон не делится на 10 000 нацело — без отбраковки маленькие исходы выпадали бы чаще больших. 1 000 000 делится, поэтому все 10 000 исходов равновероятны. Вероятность, что отклонятся все 25 окон, — порядка 10⁻³³.
hex = HMAC_SHA512(key = serverSeed, msg = clientSeed + "-" + nonce) Читаем hex окнами по 5 символов подряд (0-4, 5-9, …): первое значение < 1 000 000 → roll = значение % 10000 (если отклонены все 25 окон — roll = 9999) Меньше: выигрыш при roll < target · Больше: выигрыш при roll > target Выплата = ставка × 9900 / chanceUnits (округление вниз) · комиссия 1%
Код движка
Ровно то, что считает броски на сервере, и ровно то, что пересчитывает их в вашем браузере. Совпадение сторон закреплено тестом.
const WINDOW = 5; // hex-символов в окне: 20 бит, 0..1048575
const REJECT = 1_000_000; // наибольшее кратное 10000 в пределах окна
function roll(serverSeed, clientSeed, nonce) {
const hex = createHmac("sha512", serverSeed)
.update(`${clientSeed}-${nonce}`)
.digest("hex"); // 128 символов
// окна по 5 hex-символов подряд: 0-4, 5-9, ... 120-124
for (let i = 0; i * WINDOW + WINDOW <= hex.length; i++) {
const lucky = parseInt(hex.slice(i * WINDOW, i * WINDOW + WINDOW), 16);
if (lucky < REJECT) return lucky % 10000; // 0..9999
}
// отклонены все 25 окон (вероятность ~1e-33)
return 9999;
}
// выплата: 1% комиссии, округление вниз
const payout = (amount, chanceUnits) => amount * 9900n / BigInt(chanceUnits);
Как проверить свою игру
В мини-приложении: Честность в нижней панели, или «Проверить игру» в карточке любой ставки.
- Вкладка «Сиды» — здесь хеш действующего серверного сида. Он зафиксирован до ваших ставок.
- Смените пару сидов. Прежний серверный сид раскроется; ваш клиентский останется вашим.
- Вкладка «Раскрытые» — раскрытый сид лежит рядом со своим хешем. Сверьте: SHA-256 сида обязан совпасть с тем, что показывался до ставок.
- Вкладка «Проверка» — вставьте серверный сид, клиентский сид и nonce нужной ставки. Бросок пересчитается прямо в браузере и сравнится с результатом игры.
Расчёт идёт на вашем устройстве и к нашему серверу не обращается. По формуле выше его можно повторить в любом языке — HMAC-SHA512 есть везде.