The flowchart's WITHDRAW node (E1) stated that a withdrawal cannot happen together with a bet in progress. The code only serializes the two *builds* through the per-user lock: a withdrawal is accepted while a bet is still unconfirmed, as long as confirmed, unspent UTXOs cover it. CLAUDE.md makes every node of the diagrams binding, so one of the two had to move, and it is the diagram. The hazard the node was reaching for is the two transactions picking the same UTXO, and that is already excluded twice: app/tx/locks.py keeps the builds from overlapping, and select_utxos skips anything already marked spent_txid. What the node forbade on top of that is spending untouched, confirmed money — so implementing it as written would freeze a user's whole balance for a block after every bet and protect nothing. E1 now describes the real rule, and CLAUDE.md's per-user-lock paragraph states it is the only exclusion between the two. Regenerated the A4/A3 PDFs (gitignored, so not in this commit). The regression test is behavioural, not a wording check: it funds a user with two confirmed UTXOs, bets (taking the larger), and asserts the withdrawal goes through on the other one with the bet still unconfirmed and neither transaction spending the other's input. A second test keeps the diagram from drifting back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
69 lines
3.2 KiB
Markdown
69 lines
3.2 KiB
Markdown
# PLM Lottery
|
|
|
|
A periodic-round lottery system built on PLM, a Bitcoin-like coin (mainnet).
|
|
Each user gets a dedicated server-derived P2WPKH address; they deposit PLM to
|
|
that address, place a fixed-cost bet to enter the current round, and when the
|
|
round closes a winner is drawn who receives 70% of the prize pool (the
|
|
remaining 30% goes to fees).
|
|
|
|
This is a **custodial** system: private keys are generated and held
|
|
server-side, encrypted at rest. See [CLAUDE.md](CLAUDE.md) for the full
|
|
architecture, domain decisions, and known gaps before treating this as
|
|
production-ready.
|
|
|
|
## Quick start
|
|
|
|
The server always runs via Docker (app + Caddy reverse proxy with automatic
|
|
TLS) — in dev and production alike, with only `SITE_ADDRESS` differing
|
|
between the two. There's no supported way to run `uvicorn` directly; the
|
|
venv is only for local tooling (tests, Alembic migrations, the one-time key
|
|
scripts) — see [CLAUDE.md](CLAUDE.md#commands).
|
|
|
|
```bash
|
|
cp .env.example .env # then fill in the generated secrets, see docs/setup.md
|
|
mkdir -p data/db data/keys data/logs
|
|
docker compose run --rm app python scripts/generate_master_key.py
|
|
docker compose up -d --build
|
|
```
|
|
|
|
Open `https://localhost/` for the test UI, `https://localhost/admin` for the
|
|
admin dashboard (a self-signed-certificate warning on first visit is
|
|
expected in dev — accept it, or use `curl -k`). The interactive API docs at
|
|
`/docs` are disabled by default (they'd otherwise expose the whole API
|
|
surface, admin endpoints included) — set `ENABLE_API_DOCS=true` in `.env` to
|
|
enable them.
|
|
|
|
See [docs/setup.md](docs/setup.md) and
|
|
[docs/running-the-server.md](docs/running-the-server.md) for the full
|
|
walkthrough (secrets, master key generation, production TLS with a real
|
|
domain).
|
|
|
|
## Documentation
|
|
|
|
- [CLAUDE.md](CLAUDE.md) — architecture, commands, domain decisions, known gaps (for anyone/anything working on the code)
|
|
- [flowchart/](flowchart/) — the source-of-truth flow diagrams the implementation follows node-by-node: [platform-overview.mmd](flowchart/platform-overview.mmd) (the 5-phase flow) and [round-lifecycle.mmd](flowchart/round-lifecycle.mmd) (the round/draw lifecycle)
|
|
- [docs/setup.md](docs/setup.md) — one-time setup (secrets, master key, migrations)
|
|
- [docs/running-the-server.md](docs/running-the-server.md) — how to launch it with Docker+Caddy (dev vs. production TLS)
|
|
- [docs/guida-utente.md](docs/guida-utente.md) — end-user guide to the test UI (Italian)
|
|
- [docs/guida-admin.md](docs/guida-admin.md) — admin dashboard guide (Italian)
|
|
|
|
## Tech stack
|
|
|
|
Python (FastAPI, SQLAlchemy async + Alembic, Argon2 + JWT auth), Electrum
|
|
protocol for PLM network access (no full node), Docker + Caddy for
|
|
deployment. See [CLAUDE.md](CLAUDE.md#tech-stack) for the complete list
|
|
and the reasoning behind each choice.
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
python -m pytest # all tests
|
|
python -m pytest tests/unit/test_hd.py # one file
|
|
```
|
|
|
|
351 unit tests cover HD derivation, PSBT building, the Electrum client, bets,
|
|
deposits, withdrawals, the round/draw engine, RBF fee-bumping, admin config,
|
|
the pending-inclusive balance calculation, and the SSE push channel. No
|
|
automated integration tests against a live Electrum connection — mainnet
|
|
verification so far has been manual (see CLAUDE.md's "Project status").
|