Una mattina ho notato un articolo su sulla piattaforma Waves.
Il quadro generale era chiaro, ma il modo specifico di attuazione no. Qualcosa riguardo codici, firme, cosa, dove, perché?
Dopo alcune consultazioni con l'autore dell'oracolo, siamo riusciti a combinare la logica del sorteggio (realizzata in PHP) con l'algoritmo per generare numeri casuali.
- Al momento dell'avvio del torneo/round, chiediamo all'oracolo la prima parte del codice (R-code).
In quel momento non ci sono informazioni né sul numero di giocatori, né sul numero di premi, né sull'importo delle vincite e nemmeno sull'esistenza della lotteria. L'oracolo fornisce tramite una transazione un codice casuale personale, che può essere utilizzato solo una volta e solo da chi l'ha richiesto. A proposito, il R-code può essere "acquistato" in anticipo (si intende il costo della transazione di richiesta + compenso all'oracolo per la transazione di risposta, che è una somma di circa $0,015 al tasso attuale; il codice stesso viene fornito gratuitamente) in diverse unità, in modo da non dover aspettare la risposta della transazione. Ho creato un piccolo buffer regolarmente aggiornato nel database.
- Il torneo dura standard 60 blocchi della piattaforma blockchain Waves, attualmente circa 1 ora. Il torneo è considerato valido e chiuso se, dopo 60 blocchi, ci sono almeno due biglietti; in caso contrario, il periodo di attivazione del torneo viene esteso per altri 60 blocchi.
- Subito dopo la chiusura del torneo, generiamo e inviamo una transazione di dati (per la quale paghiamo anche una commissione di circa $0.005). Se necessario, possiamo inviare più transazioni, nelle quali sono registrati tutti i termini del sorteggio e un elenco ordinato di giocatori (biglietti) da cui dobbiamo selezionare i vincitori.
- A questo punto abbiamo già la prima parte del codice (R-code) più l'ID della transazione (TXID). Li inviamo per la firma all'oracolo concatenando (R-code + TXID), pagando nuovamente commissioni e compensazioni. L'oracolo verifica i dati ricevuti per unicità e appartenenza, e in risposta ci invia la seconda parte del codice (S-code) in formato sha256, che rappresenta il punto di partenza per il generatore di numeri casuali.
- Per ottenere un numero casuale che indichi la posizione del biglietto vincente, trasformiamo il S-code da dati binari sha256 in una rappresentazione esadecimale (HEX). Dopodiché, dall'HEX ottenuto, ricaviamo un numero. Facciamo il resto della divisione del numero risultante per il numero totale di biglietti (all_tickets) e aggiungiamo 1 al risultato (per ottenere un valore da 1 a all_tickets). Alla fine, otteniamo il numero di posizione del vincitore.
- Se le condizioni del sorteggio prevedono più vincitori, ripetiamo le operazioni precedenti per il numero corrispondente ai posti premiati. Ad ogni iterazione, rimuoviamo dalla lista il biglietto che ha già vinto e riduciamo all_tickets di 1, sostituendo il S-code con il numero ottenuto precedentemente.
Analizziamo un caso reale concreto, torneo n. 119:
Totale 7 biglietti (all_tickets)
Prezzo del biglietto 50 monete (Bet)
Raccolta di gioco 10% (Fee)
In base alle condizioni della lotteria, il 30% va ai premi, quindi in questo caso 2 biglietti devono ricevere un premio il cui valore si calcola con la formula (Bet*all_tickets-Fee) / 2.
1. Abbiamo ottenuto il R-code:
2. Dopo la chiusura del torneo, abbiamo un elenco di biglietti sotto forma di coppie: numero + indirizzo (indirizzo del portafoglio da cui è stato effettuato il pagamento per partecipare al torneo). Nota che gli indirizzi possono ripetersi, ciò significa che un partecipante ha acquistato più biglietti per lo stesso torneo, questo non è vietato dalle regole.
Abbiamo inviato la data della transazione:
3. Abbiamo richiesto il S-code: con il commento (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S
4. Abbiamo ricevuto il S-code:
5. Abbiamo determinato i vincitori.
6.
Di conseguenza, abbiamo nel blockchain una registrazione passo-passo della procedura di estrazione dei premi, con la possibilità di verificarla in qualsiasi momento. Manipolare i risultati da parte dell'organizzatore è praticamente impossibile, almeno non sarà più possibile farlo in modo invisibile.
determinare il vincitore n. 1
Tutti_i_biglietti:
Indice: 1 Biglietto:139
Indice: 2 Biglietto:141
Indice: 3 Biglietto:143
Indice: 4 Biglietto:145
Indice: 5 Biglietto:147
Indice: 6 Biglietto:149
Indice: 7 Biglietto:151
1. bin -> hex ( bin2hex(sha256(S-code)) ): Ri89jHB4UXZDXY6gT1m4LBDXGMTaYzHozMk4nxiuqVXdC -> 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596
2. hex -> numero gmp: 0xdaf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 99037963059744689166154019807924045947962565922868104113173478160267437352342
3. gmp -> modulo (mod=7): 99037963059744689166154019807924045947962565922868104113173478160267437352342 -> 4
4. modulo -> biglietto: 4 -> 145
determinare il vincitore n. 2
Tutti_i_biglietti:
Indice: 1 Biglietto:139
Indice: 2 Biglietto:141
Indice: 3 Biglietto:143
Indice: 4 Biglietto:147
Indice: 5 Biglietto:149
Indice: 6 Biglietto:151
1. bin -> hex ( bin2hex(sha256(hex precedente)) ): daf5802953dcb27f89972e38e8900b898733f6a613e6e1c6c5491362c1832596 -> 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0
2. hex -> numero gmp: 0x9560e77525e9ea2db92cdb8484dc52046ccafac7c719b8859ff55f0eb92834a0 -> 67565829218838067182838043983962684143266386786567427968312120473742580659360
3. gmp -> modulo (mod=6): 67565829218838067182838043983962684143266386786567427968312120473742580659360 -> 1
4. modulo -> biglietto: 1 -> 139
Fine.Fonte: habr.com
