An adversarial posting set of two MaxInt64 legs plus one of 2 wraps to zero in int64 arithmetic, so the balance check passed and the ledger minted 18 quintillion millisatoshis from nothing. The sum is now accumulated in big.Int, per-account balance arithmetic is checked for wraparound, and the audit totals parse through big.Int so a corrupt ledger reports a clear error rather than failing to scan. Adds room package tests (0% -> covered) and ledger edge cases. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Quantum Arcade
A private physics arcade for one Linux box and the people on your network. Drop-in crash rounds, instant scratch tickets, a real double-entry ledger, and outcomes any player can verify on their own phone.
What it is
Three shared crash games — a rocket fighting gravity, a decaying orbit, and a stacking tower — running on a five-minute heartbeat, plus instant scratch tickets to play between rounds. Identity is a keypair your browser generates; there is no account, no email, and no password.
Everything runs on one machine: one Go binary with the client embedded, PostgreSQL, and Redis.
Running it
docker compose up -d
Then open http://<your-box>:8080 from any phone on the network.
To play with test funds before Lightning is wired up:
ARCADE_DEV_FAUCET=1 docker compose up -d
The faucet mints through the same ledger path a real deposit uses, so the code under test is the production code. Leave it off otherwise.
Development
docker compose up -d postgres
go test ./...
go run ./cmd/arcade
End-to-end tests need a live server:
ARCADE_DEV_FAUCET=1 go run ./cmd/arcade &
ARCADE_E2E=http://localhost:8080 go test ./cmd/arcade/ -v
How fairness works
Before betting opens, the server generates a random seed and publishes
SHA-256(seed). It is now committed and cannot change its mind.
The client seed is built from the public keys of everyone who joined the round. The operator does not choose who plays, so it cannot steer the outcome even knowing its own seed.
The crash point is HMAC-SHA256(serverSeed, clientSeed || nonce), run through
the simulation. After settlement the seed is published, and the Verify tab
recomputes the whole chain in your browser — it asks the server only for the
published values, never for a verdict.
Scratch tickets use the identical pipeline, and their odds tables are generated from the same data structure that produces outcomes, so the published odds cannot drift from reality. A test asserts observed frequencies and empirical return against the published figures across two million plays.
Architecture
One binary, with enforced internal boundaries:
| Package | Responsibility |
|---|---|
pkg/fixed |
Q32.32 fixed-point arithmetic; no floats, so results are identical everywhere |
pkg/sim |
Deterministic RNG and the crash curve |
pkg/fair |
Commit-reveal protocol and verification proofs |
pkg/ledger |
Append-only double-entry accounting |
pkg/scratch |
Scratch tickets and their published odds |
pkg/identity |
Keypair sign-in via signed challenge |
pkg/room |
Round lifecycle and live broadcast |
Nine services on one machine would buy latency and 3am debugging, so this is one process. Modules talk through interfaces only; extracting one into its own service later is a transport change, not a rewrite.
Ledger invariants
Enforced in the application and again by database constraints and triggers:
- every transaction's postings sum to exactly zero
- no account may go negative, except the Lightning bridge, whose negative balance is by definition what is owed to players
- rows are never updated or deleted; corrections are compensating entries
GET /api/health sums every account. It must return zero. Anything else means
the books are corrupt.
Round timing
The multiplier follows m(t) = 1/(1 - t/T)², which diverges at exactly 60
seconds. No round can run longer, however extreme the crash point, and the
climb visibly accelerates as it goes — which is where the tension comes from.
Status
Built and tested:
- fixed-point deterministic core, ledger, commit-reveal fairness
- three crash games with live multiplayer rounds
- two scratch tickets with verified-honest odds
- keypair identity, peer-to-peer transfers, transaction history
- in-browser verifier
Not yet built:
- Lightning deposits and withdrawals. The bridge account and ledger paths exist; the node integration does not. The dev faucet stands in for now.
- Tournaments and scheduled events
- Operator dashboard
Scope
This is built to run on a private network among people who know each other. It is not hardened for, and should not be exposed to, the public internet. Doing so would make it a public real-money gambling service, which carries licensing, KYC, and AML obligations this codebase does not address.