Проверка исхода Crash-игры: алгоритм, безопасность

1) Цель проверки: что именно вы подтверждаете

Неподменяемость: оператор не мог изменить результат после вашей ставки (за счёт коммита хеша серверного сида).
Воспроизводимость: имея входные данные, вы получаете тот же множитель, что показала игра.
Целостность процедуры: формат сообщения, инкремент `nonce`, правило округления и «house edge» применены строго по спецификации.

2) Данные, без которых проверка невозможна

1. Server Seed Hash (коммит) — публикуется до использования соответствующего `Server Seed`.
2. Server Seed (раскрывается позже/по окончании периода).
3. Client Seed (ваш сид; вы задаёте его сами или платформа генерирует).
4. Nonce (счётчик ваших ставок в рамках текущего `Server Seed`).
5. Алгоритм хеширования (обычно `HMAC-SHA256` или `SHA-256`).
6. Формат сообщения (пример: `":"`), точные разделители/регистр/кодировка.
7. Формула маппинга хеша → множитель (и правило округления/минимума).

💡Вся спецификация должна быть в разделе Fairness / Provably Fair у оператора. Если чего-то нет — это красный флаг (см. §10).

3) Алгоритм проверки (7 шагов)

1. Сверьте коммит: посчитайте `SHA-256(ServerSeed)` и сравните с опубликованным `ServerSeedHash`.
2. Соберите сообщение: строго в формате платформы (например, `msg = ClientSeed + ":" + Nonce`).
3. Посчитайте раундовый хеш:
  • при `HMAC-SHA256`: `RoundHash = HMAC_SHA256(key=ServerSeed, msg=message)`;
при `SHA-256`: `RoundHash = SHA256(ServerSeedmessage)` или как указано в спецификации.
4. Извлеките случайность: возьмите первые `k` бит (часто 52) → целое `r`, затем `u = r / 2^k`.
5. Примените формулу маппинга: преобразуйте `u` в множитель (house edge/особые кейсы учитываются по документации игры).
6. Округлите по правилам игры (например, до 2 знаков, минимум 1.00× и т. п.).
7. Сравните с итогом раунда в истории. Совпадение = корректная честность.

4) Псевдокод (можно адаптировать под Python/JS)

```python
Вставьте сюда точную формулу маппинга от вашей платформы вместо stub_mapping()

import hmac, hashlib, math

def round_hash(server_seed: bytes, client_seed: str, nonce: int) -> bytes:
  • message = f"{client_seed}:{nonce}".encode("utf-8") формат смотрите в спецификации
  • return hmac.new(server_seed, message, hashlib.sha256).digest() либо hashlib.sha256(...)

def take_u_from_hash(h: bytes, k_bits=52) -> float:
  • Берём k старших бит как целое r
  • r = int.from_bytes(h, "big") >> (256 - k_bits)
  • return r / (1 << k_bits) u в [0, 1)

def stub_mapping(u: float) -> float:
  • ЗАГЛУШКА! Замените на формулу из документации вашей игры
  • Например, иногда используют преобразование вида: crash = floor( (const / (r+1)) 100 ) / 100
  • и/или «house edge» как редкое принудительное 1.00×. Не используйте этот стуб в реальной проверке.
  • return max(1.00, round(1.0 / max(1e-12, 1.0 - u), 2))

def verify(server_seed_hex, server_seed_hash_hex, client_seed, nonce, shown_multiplier):
  • server_seed = bytes.fromhex(server_seed_hex)
  • 1) Коммит
  • assert hashlib.sha256(server_seed).hexdigest() == server_seed_hash_hex.lower()
  • 2–3) Хеш раунда
  • h = round_hash(server_seed, client_seed, nonce)
  • 4) u
  • u = take_u_from_hash(h)
  • 5–6) маппинг + округление
  • calc_mult = stub_mapping(u)
  • 7) сравнение
  • return abs(calc_mult - shown_multiplier) < 1e-9
  • ```

Важно: вместо `stub_mapping` примените точную формулу из раздела Fairness вашей платформы; иначе проверка будет некорректной.

5) Частные случаи и подводные камни

Две ставки в одном раунде: у многих платформ `nonce` увеличивается на каждую вашу ставку, даже если они сделаны в один и тот же раунд (пример: ставка A → `nonce=42`, ставка B → `nonce=43`). Проверяйте по истории.
Смена `Client Seed`: при смене сида `nonce` обычно сбрасывается (или начинается новый поток). Сверьте правила именно вашей платформы.
Батчи `Server Seed`: один `Server Seed` действует на серию раундов, затем публикуется новый коммит; не путайте семена разных периодов.
Округление/минимум: несоответствие по второму знаку — в 90% случаев ошибка в правилах округления/минимума (например, фиксированный 1.00× при спец-условии).
Кодировка/пробелы: лишний пробел/перевод строки, неверный регистр, не-UTF-8 ломают проверку.

6) Чек-лист быстрой проверки раунда

1. Совпадает ли `SHA-256(ServerSeed)` с опубликованным `ServerSeedHash`?
2. Верно ли сформирован `message` и формат `nonce`?
3. Алгоритм (`HMAC-SHA256`/`SHA-256`) и ключ/порядок полей применены строго по спецификации?
4. Маппинг и округление идентичны документации?
5. Учитываются ли особые случаи (редкий «моментальный краш», минимум 1.00×, капы)?
6. Результат совпадает с историей игры до копейки?

7) Автоматизация контроля (практика)

Логи: сохраняйте у себя `client_seed`, последовательность `nonce`, метку времени, итоговый множитель.
Сэмплинг: после «ревила» `Server Seed` прогоняйте скриптом случайные 20–50 раундов; фиксируйте процент совпадений (должен быть 100%).
Регрессия: при смене версии игры/провайдера прогоните тот же набор.
Экспорт: храните CSV/JSON с исходниками — это ваш «аудит-трек».

8) Безопасность: как не ошибиться и не дать себя обмануть

Проверяйте локально/офлайн: не полагайтесь только на веб-валидатор оператора; держите собственный скрипт.
Не доверяйте раундам без полного пакета данных: нет формулы/формата — нет верификации.
Сильный `Client Seed`: задавайте случайный, меняйте периодически (это не повышает RTP, но исключает вопросы к воспроизводимости).
TLS/сессии: вход только по HTTPS, 2FA, отслеживание входов и выгрузок истории.
Никому не передавайте `Server Seed`: он публикуется оператором после периода; ваша задача — сверить, не «добыть» его заранее.

9) Типовые «ошибки новичков»

Перепутан порядок полей (`Nonce:ClientSeed` вместо `ClientSeed:Nonce`).
Счёт `nonce` с нуля вместо единицы (или наоборот).
Использован хеш всего раунда платформы (global nonce), а нужен ваш персональный `nonce`.
Игнор округления по правилам (banker’s rounding vs floor/ceil).
Сверка с активным, а не с уже раскрытым `Server Seed`.

10) «Красные флаги» у оператора

Нет публичного Server Seed Hash до старта периода.
Нельзя задать свой Client Seed или посмотреть nonce.
Отсутствует публичная формула маппинга хеша в множитель.
История раундов не даёт минимум данных для сверки.
Формат и алгоритм менялись без уведомления/архива спецификаций.

11) Австралийский контекст (AU)

Валюта: ведите учёт выигрышей/ставок в AUD, храните выгрузки историй (поддержка, спорные вопросы).
Ответственная игра (RG): лимиты депозита/времени, паузы и самоисключение — доступны в добросовестных приложениях; используйте их.
Платформенные практики: у добросовестных операторов блок «Fairness/Provably Fair» содержит полное описание и примеры верификации; отсутствие подробностей — повод выбирать другой сервис.

12) Итог

Проверка исхода Crash-игры — это чёткая процедура:
  • сверка коммита `Server Seed Hash`,
  • восстановление `RoundHash` по `Server Seed`, `Client Seed`, `nonce` и алгоритму,
  • применение опубликованной формулы маппинга и правил округления,
  • идентичный множитель в вашей проверке и в истории игры.

Держите собственный скрипт, логируйте входные данные и периодически проверяйте случайные раунды. Так вы подтверждаете честность не на словах, а математически.