Pewnego ranka natknąłem się na artykuł o na platformie blockchain Waves.
Ogólny obraz był jasny, ale sposób konkretnej realizacji już nie. Jakieś kody, podpisy, co, dokąd, po co?
Po kilku konsultacjach z autorem orakulum udało się połączyć logikę losowania (zrealizowaną w PHP) z algorytmem generowania liczby losowej.
- W momencie rozpoczęcia turnieju/rysunku prosimy orakulum o pierwszą część kodu (R-code).
W tym momencie nie ma informacji ani o liczbie graczy, ani o liczbie miejsc nagradzanych, ani o wysokości nagród, ani o istnieniu loterii. Orakulum wydaje osobisty losowy kod w ramach transakcji, który może być użyty tylko raz i tylko przez osobę, która go zażądała. A propos, R-code można »zakupić« (choć chodzi o koszt transakcji zapytania + rekompensatę dla orakulum za odpowiednią transakcję, co wynosi około $0.015 według aktualnego kursu, sam kod jest wydawany za darmo) z wyprzedzeniem, aby później nie czekać na uzyskanie odpowiedzi. Utworzyłem mały regularnie uzupełniany bufor w bazie danych.
- Turniej trwa standardowo 60 bloków blockchaina Waves platform, co obecnie wynosi około 1 godziny. Turniej uznaje się za odbyty i zamknięty, jeśli po 60 blokach znajdują się w nim co najmniej dwa bilety, w przeciwnym razie czas aktywności turnieju jest przedłużany o kolejne 60 bloków.
- Bezpośrednio po zakończeniu turnieju formujemy i wysyłamy transakcję daty (za nią również płacimy prowizję w wysokości około $0.005), jeżeli to konieczne — kilka, w której są zapisane wszystkie warunki losowania oraz uporządkowana lista graczy (biletów), z której musimy wyłonić zwycięzców.
- Na tym etapie mamy już pierwszą część kodu (R-code) oraz ID transakcji daty (TXID). Wysyłamy je do podpisu orakulum w formie konkatenacji (R-code + TXID), ponownie płacąc prowizję + rekompensatę. Orakulum sprawdza otrzymane dane pod kątem unikalności i przynależności, a w odpowiedzi przesyła nam drugą część kodu (S-code) w formacie sha256, która jest punktem wyjścia dla generatora liczb losowych.
- Aby uzyskać losową liczbę wskazującą na numer kolejny zwycięskiego biletu, przekształcamy S-code z binarnych danych sha256 na heksadecymalne (HEX) przedstawienie. Następnie z uzyskanej HEX stringi otrzymujemy liczbę. Obliczamy resztę z dzielenia otrzymanej liczby przez liczbę biletów (all_tickets) i dodajemy do wyniku 1 (aby uzyskać cyfrę 1 do all_tickets). W rezultacie otrzymujemy numer kolejny zwycięzcy.
- Jeśli zgodnie z zasadami losowania zwycięzców jest kilku, powtarzamy poprzednie operacje w liczbie równej ilości miejsc nagrodowych. Za każdym razem usuwamy z listy bilet, który już wygrał i zmniejszamy all_tickets o 1, a zamiast S-code podajemy poprzednio uzyskaną liczbę.
Rozważmy konkretny przykład, turniej nr 119:
Łącznie 7 biletów (all_tickets)
Koszt biletu 50 monet (Bet)
Prowizja 10% (Fee)
Zgodnie z zasadami loterii 30% trafia do nagród, tj. w tym przypadku 2 bilety powinny otrzymać nagrodę, której wielkość oblicza się według wzoru (Bet*all_tickets-Fee)/2.
1. Otrzymaliśmy R-code:
2. Po zamknięciu turnieju mamy listę biletów w postaci par: numer + adres (adres portfela, z którego dokonano płatności za udział w turnieju). Zauważmy, że adresy mogą się powtarzać, co oznacza, że jeden uczestnik kupił kilka biletów w jednym turnieju, co nie jest zabronione zasadami.
Wysłano datę transakcji:
3. Poprosiliśmy o S-code: z komentarzem (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S
4. Otrzymaliśmy S-code:
5. Określiliśmy zwycięzców.
6.
W rezultacie mamy na blockchainie krok po kroku zarejestrowaną procedurę losowania nagród z możliwością jej weryfikacji w dowolnym momencie. Sfałszowanie wyników ze strony organizatora jest praktycznie niemożliwe, przynajmniej nie jest już możliwe, aby zrobić to niezauważalnie.
określ zwycięzcę nr 1
Wszystkie_bilety:
Indeks: 1 Bilet:139
Indeks: 2 Bilet:141
Indeks: 3 Bilet:143
Indeks: 4 Bilet:145
Indeks: 5 Bilet:147
Indeks: 6 Bilet:149
Indeks: 7 Bilet:151
1. bin -> hex ( bin2hex(sha256(S-code)) ): Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC -> 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596
2. hex -> liczba gmp: 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 99037963059744689166154019807924045947962565922868104113173478160267437352342
3. gmp -> modulo (mod=7): 99037963059744689166154019807924045947962565922868104113173478160267437352342 -> 4
4. modulo -> bilet: 4 -> 145
określ zwycięzcę nr 2
Wszystkie_bilety:
Indeks: 1 Bilet:139
Indeks: 2 Bilet:141
Indeks: 3 Bilet:143
Indeks: 4 Bilet:147
Indeks: 5 Bilet:149
Indeks: 6 Bilet:151
1. bin -> hex ( bin2hex(sha256(poprzedni hex)) ): daf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0
2. hex -> liczba gmp: 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0 -> 67565829218838067182838043983962684143266386786567427968312120473742580659360
3. gmp -> modulo (mod=6): 67565829218838067182838043983962684143266386786567427968312120473742580659360 -> 1
4. modulo -> bilet: 1 -> 139
Koniec.Źródło: habr.com
