Folosind un oracol aleatoriu folosind exemplul unei loterie

Într-o dimineață am dat peste un articol despre generator de numere aleatorii verificabile pe platforma Waves blockchain.

Imaginea de ansamblu a fost clară, dar metoda specifică de implementare nu a fost. Unele coduri, semnături, ce, unde, de ce?

Câteva consultări cu autorul oracolului, ca urmare, a fost posibilă combinarea logicii desenului (implementat în PHP) cu un algoritm pentru obținerea unui număr aleator.

  1. La începutul turneului/rundei, solicităm prima parte a codului (R-code) de la oracol.

    În acest moment, nu există informații despre numărul de jucători, numărul de locuri pentru premii, mărimea plăților premiilor sau existența loteriei în general. Oracolul, printr-o tranzacție, emite un cod personal aleatoriu, care poate fi folosit apoi o singură dată și doar de cei care l-au solicitat. Apropo, codul R poate fi „achiziționat” (adică costul tranzacției de solicitare + compensare către oracol pentru tranzacția de răspuns, aceasta este o sumă de aproximativ 0.015 USD la rata curentă, codul în sine este emis gratuit ) de mai multe ori în avans, pentru a nu aștepta ulterior primirea tranzacției de răspuns. Am creat un mic buffer actualizat regulat în baza de date.

  2. Turneul durează de obicei 60 de blocuri din blockchain-ul platformei Waves, momentan este de aproximativ 1 oră. Turneul este considerat finalizat și închis dacă după 60 de blocuri există cel puțin două bilete în el, în caz contrar timpul de activitate a turneului este prelungit pentru următoarele 60 de blocuri.
  3. Imediat după încheierea turneului, generăm și trimitem o tranzacție de dată (platim și un comision de aproximativ 0.005 USD pentru aceasta), dacă este necesar, mai multe, în care sunt înregistrate toate condițiile extragerii și o listă ordonată de jucători (bilete) din care trebuie să selectăm câștigătorii.
  4. În această etapă, avem deja prima parte a codului (R-code) plus ID-ul datei tranzacției (TXID). Le trimitem spre semnare oracolului sub forma de concatenare (R-code + TXID), iar noi platim comision + compensatie. Oracolul verifică datele primite pentru unicitate și apartenență și, ca 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 va indica numărul de secvență al biletului câștigător, convertim codul S din datele binare sha256 într-o reprezentare hexazecimală (HEX). Apoi, din șirul HEX rezultat, obținem un număr. Obținem restul împărțirii numărului rezultat la numărul de bilete (all_tickets) și adăugăm 1 la rezultat (pentru a obține numărul 1 înainte de all_tickets). Drept urmare, obținem numărul de serie al câștigătorului.
  6. Dacă, conform condițiilor extragerii, există mai mulți câștigători, atunci repetăm ​​operațiunile anterioare într-o sumă egală cu numărul de locuri la premiu. În acest caz, de fiecare dată când scoatem din listă un bilet care a câștigat deja și reducem all_tickets cu 1, iar în loc de S-code indicăm numărul anterior primit.

Să ne uităm la un exemplu real concret, turneul nr. 119:

Total 7 bilete (all_tickets)
Biletul costă 50 de monede (pariu)
Taxa de joc 10% (Taxa)

Conform condițiilor loteriei, 30% se îndreaptă către premiul în bani, i.e. în acest caz, 2 bilete trebuie să primească un premiu, a cărui mărime se calculează conform formulei (Bet*all_tickets-Fee)/2.

1. A primit codul R: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

2. După încheierea turneului, avem o listă de bilete sub formă de perechi: număr + adresa (adresa portofelului din care s-a făcut plata pentru participare la turneu). Vă rugăm să rețineți că adresele pot fi repetate, ceea ce înseamnă că un participant a cumpărat mai multe bilete la un turneu; acest lucru nu este interzis de reguli.

Data tranzacției trimisă: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

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

4. Cod S primit: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

5. Câștigătorii au fost stabiliți.

6. Plăți trimise

Ca urmare, avem o înregistrare pas cu pas a procedurii de extragere a premiilor în blockchain cu posibilitatea de a o verifica în orice moment. Este aproape imposibil ca organizatorul să manipuleze rezultatele; cel puțin, nu va mai fi posibil să o facă neobservată.

determine the winner № 1

All_tickets:
Index: 1 Ticket:139
Index: 2 Ticket:141
Index: 3 Ticket:143
Index: 4 Ticket:145
Index: 5 Ticket:147
Index: 6 Ticket:149
Index: 7 Ticket: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 -> ticket: 4 -> 145

determine the winner № 2

All_tickets:

Index: 1 Ticket:139
Index: 2 Ticket:141
Index: 3 Ticket:143
Index: 4 Ticket:147
Index: 5 Ticket:149
Index: 6 Ticket: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 -> ticket: 1 -> 139

End.

Sursa: www.habr.com

Adauga un comentariu