Relics
How rolls are kept fair
A relic’s roll is settled before anyone swings a sword, and you don’t have to take our word for it. Here is how, and everything you need to check it yourself.
A secret seed for every day
Each UTC day has its own seed: 32 random bytes that only the game server knows.
Its fingerprint is published first
Before the day starts, the SHA-256 hash of that seed (the commitment) is published below. The seed can’t be changed afterwards without the hash giving it away.
Every drop is rolled from it
Every roll takes the next number of the day’s public roll counter (1, 2, 3, …). A relic is rolled with HMAC-SHA256 of the seed, the day, its counter number and its slot in the kill. The first 8 bytes are the roll, the next 8 pick the pattern. No dice, no second tries.
The seed is revealed the next day
From midnight UTC the day’s seed is public, with the list of every roll the counter handed out. Anyone can hash the seed, compare it with the commitment, recompute every roll, and check that the counter runs 1, 2, 3… with nothing missing.
Every relic is signed
The server signs each relic’s certificate with its Ed25519 key, and every change of owner as a record that names the hash of the one before it, so the history can’t be quietly rewritten.
The roll, exactly
mac = HMAC-SHA256(seed, "<day>:<counter>:<slot>") roll = big-endian uint64 of mac[0..8) pattern = big-endian uint64 of mac[8..16) mod 1000 shown = floor(roll × 10⁶ / 2⁶⁴), never rounded up grade = leading nines of roll / 2⁶⁴, up to 5
What this doesn’t prove
The server knows the day’s seed, so it knows which counter numbers will roll well, and it still decides when a roll happens and which kill gets the next number. A skipped or hidden roll shows up as a gap in the counter, but the order of kills is not provable. Relics from before the counter (scheme 1) were rolled from a kill id the server chose, which it could have picked again and again.
Commitments and reveals
Newest first. Today’s and tomorrow’s seeds stay sealed; each opens at midnight UTC after its day ends.
Signing keys
Certificates and transfers are signed with Ed25519. A key id is the first 16 hex characters of the SHA-256 of its public key; old keys stay listed so older certificates keep verifying.
Verify it yourself
Every relic page checks itself in your browser: the signatures, the hash chain, and, once the day’s seed is out, the commitment and the roll. Nothing is taken from the server’s own verdict.
Or run the standalone verifier from the backend repository. It needs Python and the cryptography package:
cd backend python scripts/verify_relic.py <relic id> # the shared test vectors python scripts/verify_relic.py --vectors \ ../infrastructure/docs/relic-test-vectors.json
