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>
169 lines
8.1 KiB
Markdown
169 lines
8.1 KiB
Markdown
# Guida utente
|
|
|
|
Come usare PLM Lottery dall'interfaccia web (`https://<host>/` — vedi
|
|
[running-the-server.md](running-the-server.md) per come avviare il server).
|
|
Per cosa succede dietro le quinte (depositi, round, estrazione, pagamenti) vedi
|
|
[come-funziona.md](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:
|
|
|
|
1. **Barra di navigazione** (fissa in alto) — il tuo username e il bottone
|
|
"Esci" (logout) nella riga superiore, e i tab delle sezioni subito sotto
|
|
2. **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
|
|
3. **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:
|
|
|
|
1. conferma dell'ultima giocata rimasta in sospeso (se ce n'era una proprio
|
|
allo scadere del timer — altrimenti questo passo è già superato);
|
|
2. 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;
|
|
3. 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 con `P...`) 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.
|