Последние 15 лет я проектирую игровые системы и слоты. Старался держаться в стороне от комплаенса, но однажды пришлось подготовить для сертификационной лаборатории детальное описание алгоритма. Я создал технически безупречный документ, отправил его — и осознал, что его никто даже не открывал. Лаборатория просто поставила печати, взяла оплату и выдала сертификат. Спустя два часа можно было выкатить хотфикс в продакшн, превратив сертифицированный хеш в бесполезный набор байтов — и это никого не интересовало.
Индустрия держится на «мертвой» документации, а не на реальной прозрачности. Это касается всех сфер: от лотерей и гача-механик до распределения школьных мест или розыгрышей билетов. Повсеместно декларируется «Provably Fair», используются server seed и хеши, но на практике их никто не проверяет — зачастую потому, что у пользователей, да и самих операторов, просто нет инструментов для верификации.
Я разработал UVS (Uncloned Verification Standard) — попытку сместить фокус доказательства честности с доверия к сторонним сертификатам на математически проверяемые данные, доступные каждому.
Инвариант: статус выводится из фактов, а не из маркетинговых деклараций
Сердце стандарта — функция deriveTier. Она присваивает розыгрышу уровень доверия, опираясь исключительно на предоставленные доказательства:
-
🔴 — «голый» seed без внешних привязок;
-
🟡 — нотариальное заверение / самостоятельный якорь / привязка к маяку без подтверждения порядка коммита;
-
🟢 — нейтральная подпись реестра, trail-immutability или outcome-binding с верифицируемым коммитом.
Нет доказательств — нет зеленого статуса. Прозрачность обеспечивает код, а не обещания.
О границах применимости: что игнорирует «Provably Fair»
UVS гарантирует, что опубликованные правила были строго соблюдены при заданных входных данных и случайности. Он НЕ утверждает, что сами входы чисты: оператор по-прежнему может подтасовать список участников или изменить пул призов. UVS закрывает только одно критическое звено — исход розыгрыша. Лучше признать это ограничение сразу, чем вводить пользователей в заблуждение.
Две ветви — вариативность случайных процессов
uvLottery (лотереи / гача) — достижимый уровень 🟢
Используется seeded-перестановка. Мы берем server seed, хешируем его с публичным раундом drand (drand, сеть quicknet, интервал 3 секунды), вычисляем score каждого участника, сортируем и распределяем призы:
combinedSeed = SHA-256( serverSeed : drandRandomness )
score(id) = SHA-256( combinedSeed : id ) // для каждого участника
Сортировка по score определяет очередность выдачи призов. Одинаковые входные данные всегда дают идентичный результат на любом языке программирования. Скрытых переменных нет.
Чтобы исключить подбор seed под нужный исход, оператор коммитит будущий раунд drand, случайность которого еще не сгенерирована. Номер раунда детерминирован временем:
round = floor((now − genesis) / 3) + 1 // genesis quicknet = 1692803367
Для уровня 🟢 этого недостаточно — нужен якорь коммита (§5.4). commitmentHash фиксируется в двух независимых RFC-3161 TSA (FreeTSA + DigiCert, разные юрисдикции), при условии, что время штампа строго предшествует публикации раунда:
genTime < timeOfRound(R)
Это доказывает, что seed был зафиксирован до того, как результат стал известен. Любой желающий может проверить всю цепочку, повторно прогнав вычисления и верифицировав токен стандартными средствами:
openssl ts -verify -digest -in token.tsr -CAfile
uvGame (интерактивная физика) — предел честности 🟡
Здесь применяется commit-reveal с input-seeded случайностью: исход зависит от закоммиченного server seed и действий игрока в реальном времени. Внешний маяк отсутствует, поэтому outcome-binding и, соответственно, уровень 🟢 здесь недостижимы.
Уникальный движок: WASM на лету
Название «Uncloned» подчеркивает уникальность сессии. Логика PADDLA не статична: реестр выдает regSeed, из которого клиент генерирует WASM-модуль прямо в браузере.
buildWasm(regSeed) использует детерминированный LCG для формирования последовательности арифметических операций. Затем на лету собирается валидный wasm-бинарник, экспортирующий функцию compute(i32) -> i32:
function buildWasm(regSeed) {
const lcg = new LCG(regSeed); // LCG, посеянный seed реестра
const n = lcg.range(4, 7);
const steps = Array.from({ length: n }, () => ({
shiftOp: SHIFT_OPS[lcg.range(0, SHIFT_OPS.length)],
shiftAmt: 8 + lcg.range(0, 8),
binOp: BINARY_OPS[lcg.range(0, BINARY_OPS.length)],
constVal: (lcg.next() | 1) | 0,
}));
// ...генерация секций wasm и тела функции в LEB128...
return { bytes: new Uint8Array([0x00,0x61,0x73,0x6d, 0x01,0x00,0x00,0x00, /* ... */]) };
}
После завершения сессии лог фиксируется через RFC-3161-штампы в изолированном контуре «3A». Путь к уровню 🟢 через trail-immutability зарезервирован, но пока не востребован.
Архитектура: изолированный контур
Криптографические операции вынесены в отдельный бэкенд «3A», отделенный от основного реестра и игровых серверов. Основные эндпоинты: /commit (запуск процесса), /reveal (верификация исхода) и /anchor-record (нотаризация).
О задержках
Процесс якорного /reveal занимает около 10 секунд. Это не техническое ограничение криптографии, а преднамеренная пауза для ожидания публикации раунда drand, что исключает любые попытки подтасовки.
О роли LLM
Я — Core Java-разработчик. Использовал LLM для помощи с фронтендом, но суть UVS в том, что реализации верить не нужно: результат проверяется независимо на четырех языках программирования. Код — лишь инструмент выражения протокола.
Попробовать на практике
Все исходники и инструменты доступны:
-
Спецификация и верификаторы (JS/Python/Java/C++): github.com/constarik/uvs
-
/draw — демонстрация in-browser (🟡) против anchored (🟢): uvs.uncloned.work/draw
-
PADDLA — интерактивная игра: paddla.uncloned.work. Проверьте RFC-3161-токен через
openssl ts -verify.
Вектор развития
Асинхронные розыгрыши и одиночные игры полностью покрыты. Следующий вызов — масштабирование UVS на real-time мультиплеер с сохранением детерминизма, несмотря на сетевые задержки, потери пакетов и необходимость отката состояния. Это задача совершенно иного уровня сложности.
Буду рад обратной связи по deriveTier, схеме с двумя TSA и вашим идеям относительно детерминированного мультиплеерного netcode.


