Player identity is now Ed25519 and ML-DSA-65 (NIST FIPS 204) together,
both signatures required. An attacker must break lattice assumptions and
elliptic curves, not either one — which covers both the quantum threat to
Ed25519 and the possibility that a 2024 lattice standard does not hold.
Signatures are domain-separated to this application so one captured from
another ML-DSA protocol cannot be replayed.
Licensed AGPL-3.0: a fork stood up as a service must publish its changes,
which is what keeps a provably-fair platform honest.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Auto cash-out closes a position at exactly the chosen target rather than
the next tick's multiplier, and fires whenever the target is at or below
the crash point. This is the feature that makes the game playable over a
network, where manual timing is at the mercy of latency.
House edge drops from 2% to 1% across crash and scratch. Scratch prize
tables retuned so the published 99% RTP is exact.
Adds docs/API.md: the client uses no private endpoints, so anyone can
write a bot against the same API.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
At u=1 the unsigned quotient exceeded int64 and wrapped negative, so the
rarest and most valuable outcome silently became an instant 1.00x loss.
At u=2 it produced a 2.1-billion-times payout the house could never
cover, which would have left settlement failing and the player unpaid.
The crash point is now capped at the largest multiplier the curve can
express, which is unreachable anyway since the round hits its tick
ceiling first.
FromInt now panics outside the Q32.32 integer range instead of wrapping
a positive input into a negative value.
Raises coverage to 88% overall; adds a Makefile with db-reset, since the
append-only ledger steadily consumes bridge headroom across test runs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Round length is now bounded: the multiplier follows a hyperbolic curve
diverging at 60s, replacing an exponential one where a 275x crash point
produced a two-and-a-half minute round.
Fixes seed reveal, which silently failed every round because pgx cannot
encode a fixed-size byte array as bytea.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Scratch odds tables are derived from the same tier list that generates
outcomes, so the published odds cannot drift from reality. Tests assert
observed frequencies and empirical RTP against the published figures;
the initial prize tables claimed 98% but actually paid 56%.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Lightning bridge is modelled as the boundary with the outside
world and is the one account permitted to go negative; its negative
balance is exactly what is owed to players inside the system. All
other accounts are floored at zero by both the application and a
database trigger.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seed expansion uses SplitMix64 so all 32 seed bytes affect the stream;
copying the seed directly into xoshiro state left the first draw
dependent only on bytes 8-15.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>