Come funziona un'estrazione — un esempio pratico
Segui un'estrazione reale dall'inizio alla fine: 1.000 commenti idonei, 3 vincitori, 9 riserve. Nessun gergo tecnico, nessuna ambiguità.
Lo scenario
Immagina che il concorso sia terminato. I commenti sono stati recuperati, i filtri del concorso sono stati applicati e 1.000 partecipazioni sono idonee. Il premio assegna 3 vincitori con 9 riserve, nel caso in cui alcuni vincitori non possano essere raggiunti. Ecco la probabilità per ogni partecipazione — identica per ognuno dei 1.000 commenti idonei, indipendentemente da quando è stato pubblicato o dalla lunghezza del nome del commentatore.
| Esito | Probabilità per ogni partecipazione |
|---|---|
| Estratto come vincitore principale (posizioni 1–3) | 3 su 1.000 — 0,30% |
| Estratto come riserva (posizioni 4–12) | 9 su 1.000 — 0,90% |
| Estratto in qualsiasi posizione vincente | 12 su 1.000 — 1,20% |
Nulla di tutto ciò cambia se il concorso ha 444 commenti o 444.444. L'algoritmo è identico. Cambia solo il denominatore.
Passo 1 — Raccogliere e filtrare le partecipazioni
L'app recupera ogni commento dal post Facebook o Instagram collegato, poi applica i filtri del concorso — duplicati, parole bloccate, regole sull'età dell'account, qualunque cosa sia stata configurata. Ciò che sopravvive è l'insieme degli idonei. Nel nostro scenario sono 1.000 commenti. Ognuno ha una riga nel database con un ID numerico univoco; quei 1.000 ID sono su cui opera il resto dell'estrazione.
Passo 2 — Ordinarli in un ordine canonico
Prima che accada qualcosa di casuale, l'app ordina i 1.000 ID in rigoroso ordine numerico crescente — 17, 142, 203, 1058, 9941, … — e scarta l'ordine di arrivo. Perché? Perché Facebook può restituire i commenti in ordini diversi a seconda della paginazione, dell'ora del giorno o di modifiche al back-end. Se l'estrazione usasse l'ordine di Facebook, due nuovi recuperi potrebbero produrre vincitori diversi dallo stesso seed casuale. Ordinare prima blocca l'input su un unico elenco canonico, così il seed da solo determina il risultato.
Passo 3 — Bloccare l'elenco di input con un hash SHA-256
L'elenco ordinato viene passato a SHA-256 — una funzione crittografica di hash — producendo un'impronta digitale di 64 caratteri. L'impronta, insieme all'elenco completo, viene salvata sul record del concorso. Da questo momento in poi, chiunque esamini il concorso può confermare che l'elenco degli idonei non è stato alterato: ricalcola l'hash dell'elenco pubblicato, confrontalo con l'impronta salvata, e un singolo ID modificato produce un hash completamente diverso. Non c'è modo di aggiungere o rimuovere silenziosamente un commento dopo questo passaggio senza che sia visibile.
Passo 4 — Generare un seed casuale a 256 bit
L'app chiede alla sorgente di casualità crittografica del sistema operativo (SecureRandom.hex(32)) 32 byte di casualità imprevedibile, e memorizza il risultato come stringa esadecimale di 64 caratteri — ad esempio a3f1…ce. 256 bit significa 2²⁵⁶ ≈ 10⁷⁷ seed possibili. Per avere un punto di riferimento, l'universo osservabile contiene circa 10⁸⁰ atomi. Nessuno — né il creatore del concorso, né l'operatore, né un attaccante esterno — può prevedere o indovinare questo seed prima che venga generato.
Passo 5 — Mescolare i 1.000 ID, poi prendere i primi 12
Il seed inizializza un motore di mescolamento deterministico, che esegue un Fisher–Yates shuffle sui 1.000 ID ordinati. Fisher–Yates è l'algoritmo standard di mescolamento equo — ognuna delle 1.000 partecipazioni ha uguale probabilità di finire in ogni posizione. Dopo il mescolamento, l'app prende i primi 12 elementi dall'inizio. Questo è l'intero passaggio di selezione: mescola, prendi 12.
Passo 6 — Assegnare le posizioni
I 12 elementi selezionati vengono percorsi in ordine. I primi tre diventano vincitori 1, 2 e 3, e i successivi nove diventano riserve da 1 a 9. Le restanti 988 partecipazioni idonee vengono registrate come non selezionate. I commenti che sono stati filtrati in precedenza vengono contrassegnati come squalificati con il motivo specifico per cui non si sono qualificati.
Passo 7 — Pubblicare tutto
Infine, l'app salva cinque elementi di prova sul record del concorso — tutti leggibili pubblicamente. Senza di essi, il risultato sarebbe una scatola nera. Con essi, chiunque può riprodurre l'intera estrazione a casa propria e confermare che i vincitori pubblicati sono gli unici vincitori che il seed avrebbe potuto produrre.
Cosa viene pubblicato con ogni estrazione
Ognuno di questi è archiviato sul concorso ed esposto tramite le pagine di verifica pubbliche. Insieme rendono l'estrazione completamente riproducibile — stessi input, stessi output, sempre.
- Il seed casuale a 256 bit — la stringa esadecimale di 64 caratteri del Passo 4.
- L'elenco ordinato degli ID idonei — tutti i 1.000 ID del Passo 2, in ordine canonico.
- L'impronta SHA-256 degli ID — l'hash di 64 caratteri del Passo 3. Conferma che l'elenco pubblicato non è stato manomesso.
- La versione dell'algoritmo — attualmente
v1. Fissa il preciso algoritmo di selezione, in modo che i miglioramenti futuri non alterino retroattivamente i vecchi risultati. - La versione di Ruby — fissa il runtime del linguaggio, poiché l'ordinamento esatto del mescolamento dipende da esso.
Riproduci i calcoli tu stesso — in cinque righe
Se hai Ruby installato (è incluso in macOS e nella maggior parte delle distribuzioni Linux), puoi riprodurre l'estrazione esatta a casa. Ogni concorso pubblica il proprio eligible-ids.txt sulla sua pagina di verifica (schema URL: /results/<token>/verify) — la guida alla verifica guida passo-passo nel download. Copia il seed pubblicato e incolla questo in irb:
require "digest"
seed = "PASTE_THE_PUBLISHED_SEED_HERE"
ids = File.read("eligible-ids.txt").split("\n").map(&:to_i).sort
# (1) Sanity check the input: must equal the published SHA-256.
Digest::SHA256.hexdigest(ids.join("\n"))
# (2) Re-run the shuffle. First 3 items are winners 1..3 (in order);
# the next 9 items are reserves 1..9.
ids.shuffle(random: Random.new(seed.to_i(16))).first(12)
I 12 ID escono nello stesso identico ordine pubblicato dal concorso. Tre vincitori, nove riserve, bit per bit identici. Questo è ciò che rende verificabile un'estrazione Pick a Winner invece di essere semplicemente promessa — è la matematica a fare il lavoro, non la parola dell'operatore.
Perché è difficile manipolare questo sistema
- Il seed è imprevedibile. 2²⁵⁶ possibilità, generate solo dopo che l'elenco degli idonei è stato registrato. Nessuno può pre-calcolare quali ID il seed favorirebbe, perché il seed non esiste fino al momento dell'estrazione.
- L'input è bloccato. L'impronta SHA-256 significa che non puoi aggiungere silenziosamente il commento di un amico dopo aver visto il seed — l'impronta cambierebbe e l'estrazione non sarebbe più riproducibile.
- Il mescolamento è meccanico. Una volta che il seed e l'elenco ordinato esistono, i vincitori sono determinati. Nessuna decisione umana si interpone tra loro. Qualsiasi modifica successiva emergerebbe come discrepanza nel momento in cui chiunque riproduce i calcoli.
- La ricevuta è pubblica. Seed, elenco, hash, versione dell'algoritmo, versione di Ruby — tutti e cinque sono pubblicati. Non esiste alcun elemento privato dell'estrazione che l'operatore potrebbe modificare senza che tutti possano vederlo.