Единно утро ми попадна статия за в блокчейна Waves platform.
Общата картина беше ясна, но начинът на конкретната реализация - не. Какви кодове, подписи, какво, къде, защо?
След няколко консултации с автора на оракула, успяхме да съчетаем логиката на разиграването (реализирана на PHP) с алгоритъма за получаване на случайно число.
- В момента на стартиране на турнира/кръга, ние изискваме от оракула първата част от кода (R-code).
В този момент няма информация нито за броя на играчите, нито за броя на наградните места, нито за размера на наградите и изобщо за съществуването на лотарията. Оракулът чрез транзакция предоставя персонален случаен код, който по-късно може да бъде използван само веднъж и само от този, който го е запитал. Между другото, R-code може да бъде "закупен" (става въпрос за цената на транзакцията за запитване + компенсация за оракула за отговорната транзакция, това е сума около $0.015 по текущия курс, самият код се предоставя безплатно) предварително, за да не се чака получаването на отговорна транзакция. Направих малък редовно попълван буфер в БД.
- Турнирът продължава стандартните 60 блока в блокчейна Waves platform, в момента това е около 1 час. Турнирът се счита за състоял се и затворен, ако след 60 блока в него има поне два билета, иначе времето за активност на турнира се удължава за следващите 60 блока.
- Веднага след затварянето на турнира ние формулираме и изпращаме дата транзакцията (за нея също плащаме такса около $0.005), при необходимост - няколко от нея, в която са записани всички условия на разиграването и подреденият списък на играчите (билетите), от който трябва да изберем победителите.
- На този етап вече имаме първата част от кода (R-code) плюс ID на дата транзакцията (TXID). Изпращаме ги на оракула за подпис под формата на конкатенация (R-code + TXID), отново плащаме такса + компенсация. Оракулът проверява получените данни за уникалност и принадлежност, а в отговор ни изпраща втората част от кода (S-code) във формат sha256, която е отправната точка за генератора на случайни числа.
- За да получим случайно число, което да указва на поредния номер на спечелилото билетче, преобразуваме S-code от двоични данни sha256 в шестнадесетичен (HEX) формат. След това от получената HEX строка извличаме числа. Взимаме остатък от делението на полученото число с броя на билетите (all_tickets) и добавяме 1 (за да получим число от 1 до all_tickets). В крайна сметка получаваме поредния номер на победителя.
- Ако по условията на жребия има повече победители, повтаряме предишните операции в количество, равно на броя на наградните места. При това всеки път премахваме от списъка билета, който вече е спечелил, и намаляваме all_tickets с 1, а вместо S-code поставяме предходното получено число.
Нека разгледаме конкретен реален пример, турнир №119:
Общо 7 билета (all_tickets)
Цената на билета е 50 монети (Bet)
Игралната такса е 10% (Fee)
По условията на лотерията 30% отиват за награди, т.е. в този случай 2 билета трябва да получат награда, чиито размер се изчислява по формула (Bet*all_tickets-Fee)/2.
1. Получихме R-code:
2. След затварянето на турнира имаме списък с билети под формата на двойки: номер + адрес (адрес на портфейла, от който е извършено плащането за участие в турнира). Забележете, че адресите могат да се повтарят, което означава, че един участник е закупил няколко билета за един турнир, което не е забранено от правилата.
Изпратихме дата на транзакцията:
3. Запитахме S-code: с коментар (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S
4. Получихме S-code:
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
