The seed was the hash of the first block seen after the close, so a miner holding tickets
could withhold blocks until one made them win, the active Electrum server could pick which
real block was used by not announcing another (a failed corroboration even moved the draw to
the next block), and the participant order was the server-only `broadcast_at` with no
tie-break, so nobody could recompute the result.
- Open: every round gets a 32-byte `server_seed`, stored only Fernet-encrypted with the
master-xprv key (`server_seed_enc`), with its published `server_seed_hash`;
`draw_confirmations` is copied from round_config. The plaintext column is written only by
the reveal.
- Entering `drawing` (one transaction, `draw_committed` audit row): participants ordered by
bet txid, each `draw_position`, `participants_hash` (sha256 of `txid:vout:address\n`
lines; new `bet_vout`), `draw_height = tip_at_close + 1`. A tip of 0 keeps the round
`closing` (`draw_baseline_tip_unknown`, once per round). All persisted, so a resumed draw
reads rather than recomputes (the `_tick` branch itself is B-81).
- `_complete_draw` / `_wait_for_draw_block` replace `_wait_for_next_block`: wait for
`draw_confirmations` blocks from `draw_height`, then `ElectrumListener.agreed_block_hash`
asks every server, the active one included, for the header at that exact height (valid
work, >= 2 other answers, strict majority of all); no agreement means the same height is
asked again and `draw_header_corroboration_failed` is written once per distinct reported
hash. `draw_stalled` now counts from the last tip advance, or from when the quorum started
to fail. Seed = sha256(server_seed || block_hash || participants_hash), index = seed mod n.
- The winner, the seed and the reveal (`server_seed`, `winner_drawn` payload) are written in
one transaction; a round closing with no participants reveals too. A round opened before
this change (no commitment) is given a secret as it enters `drawing`.
- `GET /rounds/{id}/proof` (public, 404 `round_not_found`, translated in all 7 languages) and
the new fields on `GET /rounds/current`; `draw_confirmations` in `/admin/config` and the
/admin form; `server_seed_hash`/`draw_height` in `/admin/rounds`, never the secret.
- Alembic d3e8b15a7c42 (plain add_column / create_index, expression indexes untouched).
- Docs: the B-73 `*Stato:*`/`*Oggi:*` lines are gone, guides and CLAUDE.md describe the new
draw. Ambiguities resolved in api.md: the proof's participants also carry `amount_sats`
(RND-37 lists it); `seed` is decimal in the proof and hex in the audit row, as specified.
Tests changed because the spec changed: ElectrumListener.corroborate_header (asked only the
other servers about the block the active one announced) is replaced by agreed_block_hash and
its quorum tests ported; draw_winner takes the secret and the list fingerprint; the four
_wait_for_next_block scheduler tests are replaced by _wait_for_draw_block ones (fixed height,
confirmations, same-height retry, stall clock). New: test_draw_proof.py recomputes the winner
independently from the public proof, checks the plaintext secret is nowhere in the database,
the API or the log before the reveal, and that a second pass over a `drawing` round yields
the same winner. Mutation-checked: ordering by broadcast_at, an early reveal and asking the
tip instead of the draw height each fail tests.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
8.1 KiB
Guida utente
Come usare PLM Lottery dall'interfaccia web (https://<host>/ — vedi
running-the-server.md per come avviare il server).
Per cosa succede dietro le quinte (depositi, round, estrazione, pagamenti) vedi
come-funziona.md.
Registrazione e accesso
Nella schermata iniziale trovi due tab: Registrati e Login.
- Registrati: scegli username e password. Al termine ti viene assegnato automaticamente un indirizzo di deposito personale (derivato server-side) — è per sempre tuo, e riceverai anche eventuali vincite su quello stesso indirizzo.
- Login: se hai già un account, accedi con username e password.
La sessione resta salvata nel browser (fino al logout): non serve rifare login ogni volta che riapri la pagina.
La dashboard
Dopo l'accesso vedi, in ordine:
- Barra di navigazione (fissa in alto) — il tuo username e il bottone "Esci" (logout) nella riga superiore, e i tab delle sezioni subito sotto
- Card del round corrente — sempre visibile, indipendentemente dalla
sezione che stai guardando:
- numero del round e stato (aperto, in chiusura, estrazione in corso, pagamento in corso)
- timer che conta alla rovescia il tempo rimanente prima della chiusura del round
- giocatori: quanti hanno già piazzato una bet in questo round
- jackpot: quanto riceverà chi vince questo round
- Tab di navigazione con quattro sezioni:
Estrazione del vincitore
Appena il timer arriva a zero, nessun nuovo giocatore può più entrare nel round — è un "semaforo giallo": il conteggio raggiunto lo zero blocca da subito le nuove giocate, ma il round non chiude immediatamente. Se qualcuno aveva già piazzato una bet negli ultimi istanti (transazione trasmessa ma non ancora confermata), il round aspetta che anche quella si confermi prima di procedere, così nessuna giocata già fatta viene persa al confine del round. Solo a quel punto la card mostra un messaggio di stato ("Round chiuso — attesa conferma puntate…", poi "Estrazione in corso…", poi "Pagamento al vincitore in corso…") al posto del timer — la stessa cosa compare nella dashboard di ogni utente, anche di chi non ha giocato in questo round. Questo messaggio resta visibile per l'intera durata della fase (chiusura → estrazione → pagamento), perché sotto la copertina servono diverse conferme sulla rete PLM in sequenza, una diversa dall'altra:
- conferma dell'ultima giocata rimasta in sospeso (se ce n'era una proprio allo scadere del timer — altrimenti questo passo è già superato);
- un blocco di estrazione, fissato alla chiusura (il primo dopo di essa), che deve avere in tutto 3 conferme (il valore è configurabile dall'operatore) prima che il suo hash, insieme a un segreto del server impegnato all'apertura del round, scelga il vincitore;
- la conferma della transazione che paga effettivamente la vincita.
Con un blocco PLM ogni ~2 minuti, il tempo reale dall'azzeramento del timer all'accredito della vincita è quindi in media 8-10 minuti (se c'era una giocata da confermare all'ultimo istante) o 6-8 minuti (se tutte le giocate erano già confermate prima dello zero) — non pochi secondi, ed è normale.
Se hai giocato in questo round, appena il vincitore è determinato compare in aggiunta (non al posto del messaggio di stato sopra, che resta visibile finché il pagamento non è confermato) un secondo riquadro solo per te:
- "🎉 Hai vinto! +N PLM" se sei tu il vincitore — l'importo ti verrà accreditato non appena la transazione di payout viene confermata (il round successivo non si apre finché questo non accade)
- "Non hai vinto questa volta." altrimenti
Chi non ha giocato in questo round non vede mai questo secondo riquadro, solo il messaggio di stato generico. Il riquadro personale resta visibile anche dopo un refresh della pagina (persiste nel browser), fino all'apertura del round successivo — non serve restare sulla pagina per non perderlo, e se hai perso completamente la finestra in tempo reale (es. tab in background per diversi minuti), lo vedrai comunque comparire non appena riapri la dashboard.
La dashboard si aggiorna anche in tempo reale, non solo a intervalli fissi: appena qualcosa cambia sul server (una giocata, un cambio di fase del round, un nuovo blocco confermato...) la pagina lo recepisce quasi subito, senza bisogno di premere "Aggiorna" o ricaricare.
Avviso di manutenzione
Se l'operatore ha messo in pausa la lotteria per manutenzione, in cima alla pagina (visibile anche prima del login) compare un avviso: il round eventualmente in corso viene comunque completato normalmente, vincitore incluso, ma non ne parte uno nuovo finché la manutenzione non termina. L'avviso sparisce da solo appena l'operatore riprende la lotteria.
Deposito
- Il tuo saldo interno, con bottone "Aggiorna" per ricontrollarlo. Il
numero mostrato include anche il resto di una bet o un prelievo appena
inviati (non ancora confermato sulla rete) — non solo la parte già
confermata — così non sembra che il saldo sia crollato più del dovuto
subito dopo un'operazione. Il colore indica lo stato:
- verde: tutto confermato, il saldo mostrato è quello definitivo
- arancione: c'è una bet o un prelievo ancora in attesa di conferma — il numero è corretto, ma non ancora "finale"
- Il tuo indirizzo di deposito, con bottone per copiarlo negli appunti
- Il QR code dello stesso indirizzo, comodo per inviare PLM da un altro wallet scansionandolo invece di copiare l'indirizzo a mano
Per depositare, invia PLM (mainnet reale) a quell'indirizzo da un wallet esterno. Il saldo si aggiorna da solo dopo la prima conferma (e quasi subito, grazie all'aggiornamento in tempo reale); premi "Aggiorna" se vuoi comunque ricontrollarlo a mano.
Bet
Un bottone unico: piazza l'ingresso a costo fisso (mostrato in PLM) nel round corrente. Puoi avere al massimo una bet attiva alla volta. Il costo viene scalato dal tuo saldo interno.
Prelievo
Form con due campi:
- Indirizzo esterno: dove vuoi ricevere i PLM
- Importo (PLM): quanto prelevare, oppure spunta "Preleva l'intero importo" per prelevare tutto il saldo confermato senza doverlo ricopiare a mano (il campo importo si disabilita e si aggiorna da solo)
Il prelievo viene costruito e trasmesso sulla rete; la fee di rete viene scalata dall'importo richiesto (non si aggiunge separatamente). L'importo minimo prelevabile è pari alla quota fissa di ingresso al round (mostrata nella sezione Bet).
Con "Preleva l'intero importo" restano sul tuo saldo pochi satoshi (294, cioè 0,00000294 PLM): senza quel resto la transazione non potrebbe essere ritrasmessa con una fee più alta se la rete fosse lenta, e resterebbe bloccata per ore. La cifra effettivamente inviata è quindi il saldo meno quei satoshi e meno la fee di rete.
Nota: attualmente è supportato solo l'indirizzo esterno in formato P2WPKH bech32 (quelli che iniziano con
plm1q...). Non inserire indirizzi legacy (quelli che iniziano conP...) o P2SH: al momento non sono gestiti correttamente dal server.
Profilo
Due card:
- Profilo: le tue informazioni account — username, indirizzo di deposito, saldo interno e data di iscrizione. Sola lettura, nessuna modifica possibile qui.
- Impostazioni: form per cambiare la password. Serve la password attuale (per conferma) più la nuova password (minimo 8 caratteri, digitata due volte). Non richiede un nuovo login: la sessione attiva resta valida anche dopo il cambio.
Se hai dimenticato la password e non riesci più ad accedere, questa sezione non ti aiuta (serve la password attuale) — contatta l'operatore della piattaforma, che può reimpostartene una nuova dal pannello admin.
Notifiche
Ogni azione (registrazione, login, bet, prelievo, ecc.) mostra un breve
messaggio (toast) verde in caso di successo o rosso in caso di errore, in
basso nella pagina. Se qualcosa non va e il messaggio non basta a capire il
motivo, il dettaglio tecnico è nei log del server (logs/app.log o
data/logs/app.log con Docker) — non nell'interfaccia.