Zastosowanie losowego orakula na przykładzie loterii

Pewnego ranka natknąłem się na artykuł o weryfikowalnym generatorze liczb losowych 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.

  1. 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.

  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

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: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

3. Poprosiliśmy o S-code: FTF3uRyaa4F2uAyD6z5a3CNbTXbQLc7fSR6CFNVjgZYV z komentarzem (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

4. Otrzymaliśmy S-code: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

5. Określiliśmy zwycięzców.

6. Wysłano wypłaty

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

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster