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>
59 lines
2.4 KiB
SQL
59 lines
2.4 KiB
SQL
-- Rounds, bets, and the verification record for every settled outcome.
|
|
--
|
|
-- Seeds are stored so that any round can be re-verified indefinitely. The
|
|
-- server seed column is NULL until the round settles: revealing it early would
|
|
-- let a player compute the outcome before betting closes.
|
|
|
|
CREATE TABLE rounds (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
game TEXT NOT NULL, -- 'rocket', 'orbital', 'tower'
|
|
nonce BIGINT NOT NULL,
|
|
commitment BYTEA NOT NULL, -- SHA-256 of the server seed
|
|
server_seed BYTEA, -- revealed only after settlement
|
|
client_seed BYTEA, -- derived from participants
|
|
crash_point BIGINT, -- Q32.32 fixed-point
|
|
opened_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
locked_at TIMESTAMPTZ,
|
|
settled_at TIMESTAMPTZ,
|
|
CONSTRAINT reveal_is_complete CHECK (
|
|
settled_at IS NULL OR (server_seed IS NOT NULL AND crash_point IS NOT NULL)
|
|
)
|
|
);
|
|
|
|
CREATE TABLE bets (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
round_id BIGINT NOT NULL REFERENCES rounds(id),
|
|
account_id BIGINT NOT NULL REFERENCES accounts(id),
|
|
stake_msat BIGINT NOT NULL CHECK (stake_msat > 0),
|
|
-- Set when the player cashes out; NULL means they rode it to the crash.
|
|
cashout_at BIGINT, -- Q32.32 multiplier
|
|
payout_msat BIGINT,
|
|
placed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
settled_at TIMESTAMPTZ,
|
|
UNIQUE (round_id, account_id)
|
|
);
|
|
|
|
CREATE INDEX bets_round_idx ON bets (round_id);
|
|
CREATE INDEX bets_account_idx ON bets (account_id, id DESC);
|
|
|
|
CREATE TABLE scratch_plays (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
account_id BIGINT NOT NULL REFERENCES accounts(id),
|
|
ticket_id TEXT NOT NULL,
|
|
nonce BIGINT NOT NULL,
|
|
commitment BYTEA NOT NULL,
|
|
server_seed BYTEA NOT NULL,
|
|
stake_msat BIGINT NOT NULL CHECK (stake_msat > 0),
|
|
tier_name TEXT NOT NULL,
|
|
payout_msat BIGINT NOT NULL CHECK (payout_msat >= 0),
|
|
cells INTEGER[] NOT NULL,
|
|
played_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX scratch_account_idx ON scratch_plays (account_id, id DESC);
|
|
|
|
-- Rounds and plays are historical records; they are never rewritten.
|
|
CREATE TRIGGER scratch_plays_append_only
|
|
BEFORE UPDATE OR DELETE ON scratch_plays
|
|
FOR EACH ROW EXECUTE FUNCTION reject_mutation();
|