Проверь любой дроп

Результат считается из трёх значений, одно из них публикуется до игры. Подменить его нельзя — проверь сам.

Формула

hash   = HMAC_SHA256(server_seed, client_seed + ":" + nonce)
roll   = parseInt(hash.slice(0, 8), 16) / 2**32   // [0, 1)

// кейс: выбор по кумулятивным весам
target = roll * сумма_весов
предмет = первый, у которого накопленный вес >= target

// апгрейдер: сравнение с порогом
p      = (стоимость_входа / стоимость_цели) * (1 - комиссия)
p      = min(p, 0.73)            // с балансом в ставке — min(p, 0.60)
успех  = roll < p

Первые 8 символов хеша дают целое число до 2³², деление на 2³² даёт дробь в диапазоне от нуля до единицы. Дальше это число либо сопоставляется с таблицей дропа, либо сравнивается с порогом успеха. Никакой дополнительной логики между расчётом и выдачей нет.

Как это работает

  1. 1

    Сервер готовит сид заранее

    До начала игры сервер генерирует секретную строку — server seed — и публикует её SHA-256 хеш. Сам сид остаётся скрытым, но хеш нельзя подобрать обратно.

  2. 2

    Ты задаёшь свой сид

    Client seed можно поменять в любой момент. Он участвует в расчёте наравне с серверным, поэтому предсказать результат в одиночку не может ни одна сторона.

  3. 3

    Каждая игра нумеруется

    Nonce — порядковый номер ставки. Одна и та же пара сидов даёт разные результаты для разных номеров.

  4. 4

    Сид раскрывается

    После смены сида сервер публикует исходный server seed. Ты сверяешь его хеш с тем, что был показан заранее — и пересчитываешь любой свой дроп.

Проверить свой дроп

Скопируй три значения и выполни код в консоли браузера или в Node.

const enc = new TextEncoder();
const key = await crypto.subtle.importKey(
  "raw", enc.encode(SERVER_SEED),
  { name: "HMAC", hash: "SHA-256" }, false, ["sign"]
);
const sig = await crypto.subtle.sign(
  "HMAC", key, enc.encode(CLIENT_SEED + ":" + NONCE)
);
const hex = [...new Uint8Array(sig)]
  .map(b => b.toString(16).padStart(2, "0")).join("");

const roll = parseInt(hex.slice(0, 8), 16) / 2 ** 32;
console.log(roll);