Una mattina, mi è capitato sotto gli occhi un articolo su sulla piattaforma blockchain Waves.
L'idea generale era chiara, ma il metodo di attuazione specifico no. Quali codici, firme, cosa, dove, perché?
Dopo alcune consultazioni con l'autore dell'oracolo, sono riuscito a combinare la logica del sorteggio (implementata in PHP) con l'algoritmo per generare un numero casuale.
- Al momento dell'inizio del torneo/round richiediamo all'oracolo la prima parte del codice (R-code).
In quel momento non ci sono informazioni né sul numero dei giocatori, né sul numero di posti premiati, né sull'ammontare delle vincite e, in generale, sulla esistenza della lotteria. L'oracolo fornisce, tramite transazione, un codice casuale personale, che può essere utilizzato solo una volta e solo da chi lo ha richiesto. A proposito, il R-code può essere "acquistato" (si intende il costo della transazione di richiesta + compenso all'oracolo per la transazione di risposta, una somma di circa $0.015 ai tassi attuali; il codice stesso è fornito gratuitamente) in anticipo in più copie, così da non dover aspettare la ricezione della transazione di risposta. Ho creato un piccolo buffer regolarmente aggiornato nel database.
- Il torneo dura normalmente 60 blocchi della blockchain Waves, attualmente questo corrisponde a circa 1 ora. Il torneo è considerato valido e chiuso se, dopo 60 blocchi, ci sono almeno due biglietti; altrimenti, il periodo attivo del torneo si estende per altri 60 blocchi.
- Subito dopo la chiusura del torneo, formiamo e inviamo la data della transazione (per la quale paghiamo anche una commissione di circa $0.005), se necessario — più di una, in cui sono fissate tutte le condizioni del sorteggio e un elenco ordinato dei 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 in forma di concatenazione (R-code + TXID), pagando di nuovo commissione + compenso. L'oracolo verifica i dati ricevuti per la loro unicità e pertinenza, 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 il numero di ordine del biglietto vincente, trasformiamo il S-code dai dati binari sha256 in una rappresentazione esadecimale (HEX). Poi, dalla stringa HEX risultante, otteniamo un numero. Otteniamo il resto della divisione del numero ottenuto per il numero di biglietti (all_tickets) e aggiungiamo 1 al risultato (per ottenere il numero 1 fino a all_tickets). Infine, otteniamo il numero di ordine del vincitore.
- Se le condizioni dell'estrazione prevedono più vincitori, ripetiamo le operazioni precedenti per un numero pari ai posti premio. Ad ogni ripetizione, rimuoviamo dalla lista il biglietto che ha già vinto e diminuiamo all_tickets di 1, mentre al posto del S-code indichiamo il numero ottenuto in precedenza.
Analizziamo un esempio concreto, torneo n.119:
Totale 7 biglietti (all_tickets)
Prezzo del biglietto 50 monete (Bet)
Commissione di gioco 10% (Fee)
Secondo le regole della lotteria, il 30% va ai premi, cioè in questo caso 2 biglietti devono ricevere un premio, il cui importo è calcolato con la formula (Bet*all_tickets-Fee)/2.
1. Abbiamo ottenuto R-code:
2. Dopo la chiusura del torneo, abbiamo un elenco di biglietti sotto forma di coppie: numero + indirizzo (l'indirizzo del portafoglio da cui è stato effettuato il pagamento per partecipare al torneo). Notiamo che gli indirizzi possono ripetersi, il che significa che un partecipante ha acquistato più biglietti per lo stesso torneo, il che non è vietato dalle regole.
Inviato data transazione:
3. Richiesta S-code: con commento (R-code + TXID):
RdbAiAhKhveAtR4eyTKq75noMxdcEoxbE6BvojJjM13VE 82JTMzhHM5xEA2fQ9Qscd5QAJU3DAd8nShLjdVHTer5S
4. Abbiamo ottenuto S-code:
5. Abbiamo determinato i vincitori.
6.
Di conseguenza, abbiamo nel blockchain una registrazione passo dopo passo della procedura di estrazione dei premi con la possibilità di controllarla in qualsiasi momento. Manomettere i risultati da parte dell'organizzatore è praticamente impossibile, perlomeno farlo in modo non evidente non sarà più possibile.
determina 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
determina 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
