Juhusliku oraakli kasutamine loterii näitel

Ühel hommikul sattus mulle artikkel selle kohta kontrollitav juhuslike arvude generaator Waves platvormi plokiahelal.

Üldpilt oli selge, aga konkreetne teostusviis mitte. Mingid koodid, allkirjad, mis, kus, miks?

Mitmed konsultatsioonid oraakli autoriga, mille tulemusena oli võimalik ühendada joonistamise loogika (rakendatud PHP-s) juhusliku arvu saamise algoritmiga.

  1. Turniiri/vooru alguses küsime oraaklilt koodi esimest osa (R-kood).

    Hetkel puudub info mängijate arvu, auhinnaliste kohtade arvu, auhindade väljamaksete suuruse ega üldse loterii olemasolu kohta. Oraakel väljastab tehingu kaudu isikliku juhusliku koodi, mida saavad seejärel kasutada ainult üks kord ja ainult need, kes seda taotlesid. Muide, R-koodi saab “osta” (see tähendab päringutehingu maksumust + hüvitist oraaklile vastusetehingu eest, praeguse kursi järgi on see summa umbes 0.015 dollarit, kood ise väljastatakse tasuta ) mitu korda ette, et mitte hiljem oodata vastusetehingu laekumist. Tegin andmebaasi väikese regulaarselt uuendatava puhvri.

  2. Turniir kestab tavaliselt 60 plokki Waves platvormi plokiahelast, hetkel on see orienteeruvalt 1 tund. Turniir loetakse lõppenuks ja lõppenuks, kui 60 ploki järel on sellel vähemalt kaks piletit, vastasel juhul pikeneb turniiri tegevusaeg järgmise 60 ploki võrra.
  3. Kohe peale turniiri sulgemist genereerime ja saadame kuupäevatehingu (selle eest maksame ka vahendustasu ca 0.005$), vajadusel mitu, milles on kirjas kõik loosimise tingimused ja järjestatud mängijate nimekiri (piletid) mille hulgast peame võitjad välja valima.
  4. Selles etapis on meil juba koodi esimene osa (R-kood) pluss tehingukuupäeva ID (TXID). Saadame need oraaklile allkirja andmiseks konkatenatsioonina (R-kood + TXID), jällegi maksame vahendustasu + hüvitist. Oraakel kontrollib saadud andmete unikaalsust ja kuuluvust ning vastuseks saadab meile sha256 formaadis koodi teise osa (S-koodi), mis on juhuslike numbrite generaatori lähtepunktiks.
  5. Juhusliku arvu saamiseks, mis näitab võidupileti järjekorranumbrit, teisendame sha256 binaarandmetest S-koodi kuueteistkümnendsüsteemi (HEX) esituseks. Seejärel saame saadud HEX-stringist arvu. Saame saadud arvu jagamise piletite arvuga (kõik_piletid) jäägi ja lisame tulemusele 1 (et saada number 1 enne kõik_piletid). Selle tulemusena saame võitja seerianumbri.
  6. Kui vastavalt loosimise tingimustele on võitjaid mitu, siis kordame eelnevaid toiminguid auhinnaliste kohtade arvuga võrdses summas. Sel juhul eemaldame iga kord nimekirjast juba võitnud pileti ja vähendame all_tickets 1 võrra ning S-koodi asemel märgime ära eelmise saadud numbri.

Vaatame konkreetset reaalset näidet, turniiri nr 119:

Kokku 7 piletit (kõik_piletid)
Pilet maksab 50 münti (panus)
Mängutasu 10% (tasu)

Vastavalt loterii tingimustele läheb 30% võiduraha, s.o. sel juhul peab saama auhinna 2 piletit, mille suurus arvutatakse valemi järgi (Bet*all_tickets-Fee)/2.

1. Vastu võetud R-kood: RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE

2. Peale turniiri sulgemist on meil piletite nimekiri paaride kujul: number + aadress (rahakoti aadress, millelt turniiril osalemise eest tasuti). Pange tähele, et aadressid võivad korduda, mis tähendab, et üks osaleja ostis ühele turniirile mitu piletit, see pole reeglitega keelatud.

Tehingu kuupäev saadetud: 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

3. Taotletud S-kood: FTF3uRyaa4F2uAyD6z5a3CNbTXbQLc7fSR6CFNVjgZYV koos kommentaariga (R-kood + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S

4. Saadud S-kood: Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC

5. Selgus võitjad.

6. Saadetud maksed

Selle tulemusena on meil auhinna loosimise protseduuri samm-sammult salvestus plokiahelas koos võimalusega seda igal ajal kontrollida. Korraldajal on peaaegu võimatu tulemustega manipuleerida, vähemasti pole seda enam võimalik märkamatult teha.

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.

Allikas: www.habr.com

Lisa kommentaar