Някое утро ми попада статия за на блокчейн платформата Waves.
Общата картина беше ясна, но начинът на конкретната реализация — не. Какви са тези кодове, подписи, какво, къде, защо?
След няколко консултации с автора на оракула, успяхме да обединим логиката на томболата (реализирана на PHP) с алгоритъма за получаване на случайно число.
- В момента на започване на турнира/рунда, искаме от оракула първата част на кода (R-code).
В този момент няма информация нито за броя на играчите, нито за броя на наградните места, нито за размера на наградите и изобщо за съществуването на лотарията. Оракулът чрез трансакция предоставя персонален случайно код, който може да бъде използван само веднъж и само от този, който го е поискал. Между другото, R-code може да бъде "закупен" (става дума за разходите по трансакцията на заявка + компенсация на оракула за отговорната трансакция, това е сума около $0.015 по текущия курс, самият код се предоставя безплатно) предварително в няколко екземпляра, за да не се чака получаването на отговорната трансакция. Направих малък регулярно попълващ се буфер в базата данни.
- Турнирът трае стандартно 60 блока на блокчейн платформата Waves, което в момента е около 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-код)) ): Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC -> 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596
2. hex -> gmp число: 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 99037963059744689166154019807924045947962565922868104113173478160267437352342
3. gmp -> модуло (mod=7): 99037963059744689166154019807924045947962565922868104113173478160267437352342 -> 4
4. модуло -> билет: 4 -> 145
определете победителя № 2
Всички_билети:
Индекс: 1 Билет:139
Индекс: 2 Билет:141
Индекс: 3 Билет:143
Индекс: 4 Билет:147
Индекс: 5 Билет:149
Индекс: 6 Билет:151
1. bin -> hex ( bin2hex(sha256(предишен hex)) ): daf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0
2. hex -> gmp число: 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0 -> 67565829218838067182838043983962684143266386786567427968312120473742580659360
3. gmp -> модуло (mod=6): 67565829218838067182838043983962684143266386786567427968312120473742580659360 -> 1
4. модуло -> билет: 1 -> 139
Край.Източник: habr.com
