Utilizarea unui oracle aleatoriu pe exemplul unei loterii

Într-o dimineață, am dat peste un articol despre un generator de numere aleatorii verificat pe blockchainul platformei Waves.

Imaginea generală era clară, dar metoda de implementare specifică - nu. Ceva coduri, semnături, ce, unde, de ce?

După câteva consultații cu autorul oracolului, am reușit să combin logica tragerii la sorți (implementată în PHP) cu algoritmul de generare a numărului aleatoriu.

  1. În momentul începerii turneului/ rundei, solicităm oracolului prima parte a codului (R-code).

    În acel moment, nu există informații despre numărul de jucători, numărul de locuri premii, dimensiunea plăților premii și chiar existența loteriei. Oracolul, printr-o tranzacție, emite un cod aleatoriu personalizat, care poate fi utilizat o singură dată și doar de cel care l-a solicitat. Apropo, R-code-ul poate fi „achiziționat” (se referă la costul tranzacției de solicitare + compensația oracolului pentru tranzacția de răspuns, aceasta este aproximativ $0.015 la cursul actual, iar codul este eliberat gratuit) dinainte în mai multe exemplare, astfel încât să nu așteptăm primirea tranzacției de răspuns. Am creat un mic buffer completabil regulat în baza de date.

  2. Turneul durează standard 60 de blocuri pe blockchainul platformei Waves, ceea ce este aproximativ o oră. Turneul este considerat valid și închis dacă după 60 de blocuri există cel puțin două bilete, în caz contrar timpul de activitate al turneului se prelungește cu următoarele 60 de blocuri.
  3. Imediat după închiderea turneului, generăm și trimitem o tranzacție de date (pentru care plătim și o comision de aproximativ $0.005), dacă este necesar - mai multe, în care sunt stabilite toate condițiile tragerii la sorți și lista ordonată a jucătorilor (bilete) din care trebuie să alegem câștigătorii.
  4. În această etapă avem deja prima parte a codului (R-code) plus ID-ul tranzacției de date (TXID). Le trimitem pentru semnare oracolului sub formă de concatenare (R-code + TXID), plătim din nou comision + compensație. Oracolul verifică datele primite pentru unicitate și apartenență, iar în răspuns ne trimite a doua parte a codului (S-code) în format sha256, care este punctul de plecare pentru generatorul de numere aleatorii.
  5. Pentru a obține un număr aleatoriu care să indice ordinea biletului câștigător, transformăm S-code din datele binare sha256 în reprezentarea sa hexazecimală (HEX). Apoi, din șirul HEX obținut, extragem un număr. Obținem restul împărțirii numărului rezultant la numărul de bilete (all_tickets) și adăugăm 1 la rezultat (pentru a obține cifra 1 până la all_tickets). În final, obținem numărul de ordine al câștigătorului.
  6. Dacă, conform regulilor extragerii, există mai mulți câștigători, repetăm operațiile anterioare de un număr de ori egal cu numărul de locuri câștigătoare. De fiecare dată, eliminăm din listă biletul care a câștigat deja și reducem all_tickets cu 1, iar în loc de S-code indicăm precedentul număr obținut.

Să analizăm un exemplu concret, turneul nr. 119:

În total 7 bilete (all_tickets)
Prețul biletului este de 50 de monede (Bet)
Taxa de joc este de 10% (Fee)

Conform regulilor loteriei, 30% merg la premii, adică, în acest caz, 2 bilete ar trebui să primească un premiu, al cărui montan se calculează conform formulei (Bet*all_tickets-Fee)/2.

1. Am obținut R-code: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

2. După închiderea turneului avem o listă de bilete sub formă de perechi: număr + adresă (adresa portofelului de la care a fost efectuată plata pentru participarea la turneu). Observăm că adresele se pot repeta, ceea ce înseamnă că un participant a cumpărat mai multe bilete în același turneu, ceea ce nu este interzis de regulile jocului.

Am trimis data tranzacției: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

3. Am solicitat S-code: FTF3uRyaa4F2uAyD6z5a3CNbTXbQLc7fSR6CFNVjgZYV cu comentariul (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

4. Am obținut S-code: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

5. Am stabilit câștigătorii.

6. Am trimis plățile

Ca rezultat, avem în blockchain o înregistrare pas cu pas a procedurii de extragere a premiilor, cu posibilitatea de a verifica aceasta în orice moment. A manipula rezultatele din partea organizatorului este practic imposibil, cel puțin nu se va putea face acest lucru fără a fi observat.

determinarea câștigătorului nr. 1

Toate_biletele:
Index: 1 Bilet:139
Index: 2 Bilet:141
Index: 3 Bilet:143
Index: 4 Bilet:145
Index: 5 Bilet:147
Index: 6 Bilet:149
Index: 7 Bilet:151

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

2. hex -> gmp număr: 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 99037963059744689166154019807924045947962565922868104113173478160267437352342

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

4. modulo -> bilet: 4 -> 145

determinarea câștigătorului nr. 2

Toate_biletele:

Index: 1 Bilet:139
Index: 2 Bilet:141
Index: 3 Bilet:143
Index: 4 Bilet:147
Index: 5 Bilet:149
Index: 6 Bilet:151

1. bin -> hex ( bin2hex(sha256(previous hex)) ): daf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0
2. hex -> gmp număr: 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0 -> 67565829218838067182838043983962684143266386786567427968312120473742580659360
3. gmp -> modulo (mod=6): 67565829218838067182838043983962684143266386786567427968312120473742580659360 -> 1
4. modulo -> bilet: 1 -> 139

Final.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster