Files
plm-lottery/docs/come-funziona.md
T
davideandClaude Opus 5.5 61efbb0e37 Replace flowchart/ with a traceable specification in docs/
The two Mermaid diagrams under flowchart/ described the intended flow but
had drifted from the code and carried no link back to it. docs/ now holds
the specification instead: 15 Italian documents (flows, architecture, data
model, API, security, audit log, operations, decisions and limits, bug
history) with 472 numbered requirements, each pointing at the function
that implements it and the test that covers it. docs/processo-di-modifica.md
defines the ID convention and the spec -> code -> test change workflow, and
CLAUDE.md now names docs/ as authoritative.

Writing the spec from the code also corrected stale claims in CLAUDE.md
(B-41's get_history check, BUGS.md still tracking B-71/B-72, Cache-Control
scope, the error contract's bare-string exceptions) and in the operator
guides (payouts do retry, only `drawing` fails to resume, rounds do not
open without fee_address). The B-70 doc test now pins the prose in
docs/scommesse-e-prelievi.md instead of the deleted diagram.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:16:01 +02:00

7.6 KiB

Come funziona PLM Lottery

Panoramica del funzionamento della piattaforma. È il punto di partenza: ogni sezione rimanda al documento che la approfondisce.

Documento Cosa spiega
registrazione-e-depositi.md Come nasce un account, come arrivano i fondi, come si calcola il saldo mostrato
scommesse-e-prelievi.md Come si piazza una scommessa e come si ritirano i fondi
ciclo-di-vita-del-round.md Apertura, chiusura, estrazione del vincitore, pagamento
transazioni-e-riconciliazione.md Come ogni movimento di denaro viene registrato, inviato, accelerato (RBF) e riconciliato con la catena
connessione-electrum.md Come il server parla con la rete PLM e perché non si fida di un solo server
architettura.md Struttura del codice, processi in background, configurazione, frontend, traduzioni, test
modello-dati.md Tabelle del database, campi, stati, vincoli, migrazioni
api.md Tutti gli endpoint HTTP, formato delle risposte, catalogo dei codici di errore
sicurezza.md Modello di fiducia, chiavi e segreti, autenticazione, limiti sui tentativi, header HTTP
audit-log.md Catalogo degli eventi del registro di audit
operativita.md Backup, riavvii, procedure per gli incidenti
decisioni-e-limiti.md Decisioni di progetto con le loro motivazioni, limiti noti accettati
storico-bug.md Tutti i bug B-nn trovati e corretti, con commit e test

Questi documenti sono la specifica del software: ogni regola ha un identificativo stabile (ad esempio RND-11) con il riferimento al codice che la implementa. Come si usano per modificare il software è spiegato in processo-di-modifica.md.

Per installazione e avvio vedi setup.md e running-the-server.md; per l'uso delle interfacce guida-utente.md e guida-admin.md.

In una frase

Gli utenti depositano PLM su un indirizzo personale custodito dal server, comprano un biglietto a costo fisso per il round in corso, e allo scadere del round l'hash del primo blocco successivo sceglie un vincitore, che riceve il 70% del montepremi; il 30% va alla piattaforma.

Scelte di fondo

  • Custodiale. Le chiavi sono generate e tenute dal server (una master xprv cifrata a riposo). L'utente non controlla nulla finché non preleva.
  • Un indirizzo per utente, per sempre. Lo stesso indirizzo serve per i depositi, riceve le vincite e riceve il resto di ogni scommessa e prelievo.
  • Nessun nodo completo. Tutto l'accesso alla rete passa dal protocollo Electrum (vedi connessione-electrum.md).
  • 1 conferma per ogni tipo di transazione: depositi, scommesse, pagamenti, prelievi.
  • Parametri operativi nel database, modificabili a caldo da /admin (costo della scommessa, durata del round, commissioni…). Nel file .env restano solo segreti e collegamenti infrastrutturali.

Le cinque fasi

flowchart LR
    subgraph REG["1 · Registrazione"]
        direction TB
        A1["Username + password"] --> A2["Il server deriva un indirizzo<br/>dedicato e permanente"]
    end

    subgraph DEP["2 · Deposito"]
        direction TB
        B1["L'utente invia PLM<br/>al proprio indirizzo"] --> B2{"1 conferma e<br/>corroborato dagli<br/>altri server?"}
        B2 -- "No" --> B1b["Si riprova al prossimo<br/>aggiornamento"] --> B2
        B2 -- "Sì" --> B3["Saldo accreditato"]
    end

    subgraph PLAY["3 · Scommessa"]
        direction TB
        C1{"Saldo sufficiente,<br/>nessuna scommessa attiva,<br/>round aperto e non pieno?"}
        C1 -- "Sì" --> C2["Transazione: indirizzo utente →<br/>montepremi, resto all'utente"]
        C2 --> C3{"Confermata?"}
        C3 -- "No, troppo tempo" --> C4["Commissione aumentata<br/>(RBF) e reinvio"] --> C3
        C3 -- "Sì" --> C5["Partecipante del round"]
    end

    subgraph DRAW["4 · Round ed estrazione"]
        direction TB
        D1["Scadenza del round"] --> D2["Si attendono le scommesse<br/>già in volo"]
        D2 --> D3["Il primo blocco successivo<br/>sceglie il vincitore"]
        D3 --> D4["70% al vincitore,<br/>30% alla piattaforma"]
    end

    subgraph WITHDRAW["5 · Prelievo"]
        direction TB
        E1["Indirizzo esterno + importo"] --> E2["Transazione: indirizzo utente →<br/>esterno, resto all'utente"]
        E2 --> E3{"Confermata?"}
        E3 -- "No, troppo tempo" --> E4["RBF e reinvio"] --> E3
        E3 -- "Sì" --> E5["Saldo aggiornato"]
    end

    A2 --> B1
    B3 --> C1
    B3 --> E1
    C5 --> D1
    D4 -.->|"round successivo"| C1
  1. Registrazione — registrazione-e-depositi.md
  2. Deposito — registrazione-e-depositi.md
  3. Scommessa — scommesse-e-prelievi.md
  4. Round ed estrazione — ciclo-di-vita-del-round.md
  5. Prelievo — scommesse-e-prelievi.md

Componenti

Un solo processo Python (FastAPI) dietro Caddy, con un database SQLite. Dentro il processo girano, oltre all'API HTTP, sei attività in background avviate all'avvio del server:

Attività Ogni Cosa fa
ElectrumListener connessione continua, ping ogni 60s L'unica connessione alla rete: riceve i nuovi blocchi, osserva gli indirizzi di tutti gli utenti, accredita i depositi
RoundScheduler 5s Apre e chiude i round, esegue l'estrazione, avvia e riprova i pagamenti
ConfirmationPoller 10s Porta le transazioni da "in attesa" a "confermate"
RbfBumper 30s Aumenta la commissione di ciò che non conferma entro il tempo limite
PendingTransactionReconciler all'avvio, poi 120s Confronta con la catena ogni transazione rimasta a metà
DepositReconciler 300s Ricontrolla tutti gli indirizzi, nel caso una notifica sia andata persa

La cadenza di queste attività è ciò che determina quanto in fretta il sistema si ripara da solo dopo un problema.

Le due interfacce web sono pagine statiche servite dallo stesso server, senza build né framework:

  • / — l'interfaccia per i giocatori (registrazione, deposito, scommessa, prelievo, profilo, stato del round), tradotta in 7 lingue.
  • /admin — il pannello operatore, protetto da un token condiviso, in italiano.

Entrambe interrogano periodicamente l'API e in più ascoltano un canale SSE (GET /rounds/stream): un semplice segnale "è cambiato qualcosa, ricarica" inviato a ogni evento rilevante (round aperto o cambiato di stato, scommessa o prelievo inviato, transazione confermata, deposito accreditato, nuovo blocco). Se il canale cade, le pagine continuano a funzionare con il solo polling.

Parametri principali

Parametro Valore predefinito Modificabile
Costo della scommessa 10 PLM da /admin
Ripartizione del montepremi 70% vincitore / 30% piattaforma no, è nel codice
Durata del round 600s da /admin, vale dal round successivo
Pausa tra un round e l'altro 30s da /admin, vale dal round successivo
Commissione di rete 1 sat/vB da /admin
Tempo prima di un RBF 900s da /admin
Prelievo minimo pari al costo della scommessa segue il costo
Deposito minimo nessuno —
Partecipanti massimi per round 400 no, è nel codice
Conferme richieste 1 no, è nel codice