Използване на случаен оракул на примера на лотарията

Единно утро ми попадна статия за тестируем генератор на случайни числа в блокчейна Waves platform.

Общата картина беше ясна, но начинът на конкретната реализация - не. Какви кодове, подписи, какво, къде, защо?

След няколко консултации с автора на оракула, успяхме да съчетаем логиката на разиграването (реализирана на PHP) с алгоритъма за получаване на случайно число.

  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. Изпратихме плащанията

В резултат имаме в блокчейна стъпка по стъпка фиксиране на процедурата за жребия на наградите с възможност да я проверим по всяко време. Манипулирането на резултатите от страна на организатора е практически невъзможно, понеже да го направи незабелязано вече не е възможно.

определете победителя № 1

Всички билети:
Индекс: 1 Билет:139
Индекс: 2 Билет:141
Индекс: 3 Билет:143
Индекс: 4 Билет:145
Индекс: 5 Билет:147
Индекс: 6 Билет:149
Индекс: 7 Билет:151

1. bin -> hex ( bin2hex(sha256(S-code)) ): Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC -> 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596

2. hex -> gmp number: 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 99037963059744689166154019807924045947962565922868104113173478160267437352342

3. gmp -> modulo (mod=7): 99037963059744689166154019807924045947962565922868104113173478160267437352342 -> 4

4. modulo -> билет: 4 -> 145

определете победителя № 2

Всички билети:

Индекс: 1 Билет:139
Индекс: 2 Билет:141
Индекс: 3 Билет:143
Индекс: 4 Билет:147
Индекс: 5 Билет:149
Индекс: 6 Билет:151

1. bin -> hex ( bin2hex(sha256(previous hex)) ): daf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0
2. hex -> gmp number: 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0 -> 67565829218838067182838043983962684143266386786567427968312120473742580659360
3. gmp -> modulo (mod=6): 67565829218838067182838043983962684143266386786567427968312120473742580659360 -> 1
4. modulo -> билет: 1 -> 139

Край.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster