Skip to content
Crest of the Infinite

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.

  1. A secret seed for every day

    Each UTC day has its own seed: 32 random bytes that only the game server knows.

  2. 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.

  3. 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.

  4. 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.

  5. 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