Atsitiktinio orakulo naudojimas loterijos pavyzdžiu

Vieną rytą aptikau straipsnį apie patikrinamas atsitiktinių skaičių generatorius „Waves“ platformos blokų grandinėje.

Bendras vaizdas buvo aiškus, bet konkretus įgyvendinimo būdas – ne. Kažkokie kodai, parašai, kas, kur, kodėl?

Keletas konsultacijų su orakulo autoriumi, dėl to pavyko sujungti braižymo logiką (įdiegtą PHP) su atsitiktinio skaičiaus gavimo algoritmu.

  1. Turnyro/raundo pradžioje iš orakulo prašome pirmosios kodo dalies (R-kodas).

    Šiuo metu nėra informacijos apie žaidėjų skaičių, prizinių vietų skaičių, išmokėtų prizų dydį ar apskritai apie loterijos egzistavimą. Orakulas, atlikdamas operaciją, išduoda asmeninį atsitiktinį kodą, kurį vėliau gali naudoti tik vieną kartą ir tik tie, kurie to paprašė. Beje, R kodą galima „nusipirkti“ (tai reiškia užklausos operacijos kainą + kompensaciją orakului už atsakymo operaciją, tai yra apie 0.015 USD dabartiniu kursu, pats kodas išduodamas nemokamai ) kelis kartus iš anksto, kad vėliau nelauktumėte atsakymo operacijos gavimo. Duomenų bazėje sukūriau nedidelį reguliariai atnaujinamą buferį.

  2. Turnyras paprastai trunka 60 Waves platformos blokų blokų, šiuo metu tai yra maždaug 1 valanda. Turnyras laikomas baigtu ir baigtu, jei po 60 blokų jame yra bent du bilietai, kitu atveju turnyro veiklos laikas pratęsiamas sekantiems 60 blokų.
  3. Iš karto po turnyro uždarymo sugeneruojame ir išsiunčiame datos operaciją (už ją taip pat mokame komisinį apie 0.005 USD), jei reikia, kelis, kuriuose užfiksuotos visos burtų traukimo sąlygos ir užsakytas žaidėjų sąrašas (bilietai) iš kurių turime išrinkti nugalėtojus.
  4. Šiame etape jau turime pirmąją kodo dalį (R-kodas) ir operacijos datos ID (TXID). Mes juos siunčiame pasirašyti orakului sujungimo forma (R-kodas + TXID), vėl mokame komisinį mokestį + kompensaciją. Orakulas patikrina gautų duomenų unikalumą ir priklausomybę, o atsakydamas mums atsiunčia antrąją kodo dalį (S-kodą) sha256 formatu, kuris yra atsitiktinių skaičių generatoriaus atskaitos taškas.
  5. Norėdami gauti atsitiktinį skaičių, kuris nurodys laimėjusio bilieto eilės numerį, konvertuojame S kodą iš sha256 dvejetainių duomenų į šešioliktainį (HEX) vaizdą. Tada iš gautos HEX eilutės gauname skaičių. Gautą skaičių padalijus iš bilietų skaičiaus (visi_bilietai) gauname likutį ir prie rezultato pridedame 1 (kad gautume skaičių 1 prieš visus_bilietus). Dėl to gauname nugalėtojo serijos numerį.
  6. Jei pagal burtų traukimo sąlygas yra keli laimėtojai, tai pakartojame ankstesnes operacijas suma lygi prizinių vietų skaičiui. Tokiu atveju kiekvieną kartą iš sąrašo išbraukiame jau laimėjusį bilietą ir visus_bilietus sumažiname 1, o vietoj S kodo nurodome anksčiau gautą numerį.

Pažvelkime į konkretų tikrą pavyzdį, turnyrą Nr. 119:

Iš viso 7 bilietai (visi_bilietai)
Bilietas kainuoja 50 monetų (Bet)
Žaidimo mokestis 10% (mokestis)

Pagal loterijos sąlygas piniginiam prizui tenka 30 proc., t.y. tokiu atveju 2 bilietai turi gauti prizą, kurio dydis apskaičiuojamas pagal formulę (Bet*visi_bilietai-Mokestis)/2.

1. Gautas R kodas: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

2. Turnyrui pasibaigus, turime bilietų sąrašą poromis: numeris + adresas (piniginės, iš kurios buvo apmokėta už dalyvavimą turnyre, adresas). Atkreipiame dėmesį, kad adresai gali pasikartoti, tai reiškia, kad vienas dalyvis nusipirko kelis bilietus į vieną turnyrą, tai nedraudžia taisyklės.

Sandorio data išsiųsta: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

3. Prašomas S kodas: FTF3uRyaa4F2uAyD6z5a3CNbTXbQLc7fSR6CFNVjgZYV su komentaru (R kodas + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

4. Gautas S kodas: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

5. Nugalėtojai buvo nustatyti.

6. Išsiuntė mokėjimus

Dėl to mes turime laipsnišką prizų traukimo procedūros įrašą blockchain su galimybe bet kada tai patikrinti. Organizatoriui beveik neįmanoma manipuliuoti rezultatais, bent jau nebebus įmanoma to padaryti nepastebėtai.

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.

Šaltinis: www.habr.com

Добавить комментарий