Лотерея как пример использования случайного оракула

Некоторое время назад, очередной раз модифицируя код тотализатора, подумал о создании лотереи на блокчейне. Вечером подумал, а утром увидел статью Cлучайный оракул на основе цифровой подписи в блокчейне
Не сразу всё было понятно, но, благодаря консультациям у автора оракула, удалось интегрировать алгоритм получения случайного числа в логику розыгрыша лотереи.
Первый тестовый вариант был готов через пару дней. Затем началась работа над функционалом, дизайном, оптимизацией, автоматизацией, тестирования в реальной обстановке, работа над ошибками…
На данный момент уже вырисовывается что-то похожее на законченное решение, поэтому решил поделиться.
Итак, наиболее показательный (из-за количества участников) пример из проведенных реальных розыгрышей - турнир 119 и вся техническая информация к нему, позволяющая проверить результаты розыгрыша.
Порядок действий:

  1. В момент старта турнира/раунда мы запрашиваем у оракула первую часть кода (R-code).
    В этот момент нет информации ни о количестве игроков, ни о количестве призовых мест, ни о размере призовых выплат и вообще о существовании лотереи. Оракул посредством транзакции выдает персональный случайный код, который в дальнейшем может быть использован только один раз и только тем, кто его запросил. Кстати, R-code можно «закупить» (имеется в виду стоимость транзакции запроса + компенсация оракулу за ответную транзакцию, это сумма порядка $0.015 по текущему курсу, сам код выдается бесплатно) заранее сразу несколько, чтобы потом не ждать получения ответной транзакции. Я сделал небольшой регулярно пополняемый буфер в БД, но затем отказался, т.к. в данном случае скорость получения кода не важна.

  2. Турнир длится стандартно 60 блоков блокчейна Waves platform, на данный момент это примерно 1 час. Турнир считается состоявшимся и закрытым, если после 60 блоков в нем будет не менее двух билетов, иначе время активности турнира продлевается на следующие 60 блоков.

  3. Сразу после закрытия турнира мы формируем и отправляем дата транзакцию (за нее также платим комиссию примерно $0.005), при необходимости — несколько, в которой зафиксированы все условия розыгрыша и упорядоченный список игроков (билетов) из которого нам необходимо выбрать победителей.

  4. На данном этапе у нас уже есть первая часть кода (R-code) плюс ID дата транзакции (TXID). Мы отправляем их на подпись оракулу в виде конкатенации (R-code + TXID), опять платим комиссию+компенсацию. Оракул проверяет полученные данные на предмет уникальности и принадлежности, а в ответ посылает нам вторую часть кода (S-code) в формате sha256, которая и является отправной точкой для генератора случайных чисел.

  5. Чтобы получить случайное число, которое будет указывать на порядковый номер победившего билета, мы преобразовываем S-code из бинарных данных sha256 в шестнадцатиричное (HEX) представление. Затем из получившейся HEX строки, получаем число. Получаем остаток от деления получившегося числа на количество билетов (all_tickets) и прибавляем к результату 1 (чтобы получить цифру 1 до all_tickets). В итоге мы получаем порядковый номер победителя.

  6. Если по условиям розыгрыша победителей несколько, то повторяем предыдущие операции в количестве равном количеству призовых мест. При этом каждый раз удаляем из списка билет который уже выиграл и уменьшаем all_tickets на 1, а вместо S-code указываем предыдущее полученное число.

В нашем примере (турнир №119):
Всего 7 билетов (all_tickets)
Стоимость билета 50 монет (Bet)
Игровой сбор 10% (Fee)
По условиям лотереи 30% попадают в призовые, т.е. в данном случае 2 билета должны получить приз, размер которого считается по формуле (Bet*all_tickets-Fee)/2.

  1. Получили R-code: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

  2. После закрытия турнира имеем список билетов в виде пар: номер + адрес (адрес кошелька с которого была оплата участия в турнире). Заметим, что адреса могут повторяться, это означает, что один участник купил несколько билетов в один турнир, это не возбраняется правилами.
    Отправили дата транзакцию: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

  3. Запросили S-code: FTF3uRyaa4F2uAyD6z5a3CNbTXbQLc7fSR6CFNVjgZYV с комментарием (R-code + TXID):
    RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

  4. Получили S-code: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

  5. Определили победителей.

  6. Отправили выплаты

В результате мы имеем в блокчейне пошаговую фиксацию процедуры розыгрыша призов с возможностью проверить ее в любое время. Подтасовать результаты со стороны организатора практически невозможно, по крайней мере сделать это незаметно уже не получится.

3 Симпатий