Virtual Pigeon Racing is built so that race outcomes cannot be secretly changed. Not by players, and not by us.
We achieve this with three ideas working together:
Lock race inputs before the race starts
Record a tamper-evident event log during the race
Reveal proof data after the race so anyone can verify the result
Fairness guarantees at a glance
This table summarizes what we guarantee in every official race and the mechanism that enforces it.
Guarantee | What it means | Technical |
Immutable outcome | Race result cannot change retroactively. | Hash chain + cryptographic seal |
No secret modification | Stats, traits, AI decisions cannot be silently altered. | HMAC-SHA256 payload binding |
No randomness re-roll | Server cannot retry RNG to pick a preferred winner. | Deterministic PRNG seeded pre-race |
Independent verifiability | Anyone can audit every step post-race. | Full reveal + public event log |
Live race support | Race evolves in real-time. No T-10 lock needed. | Event sourcing + streaming |
The exact lock timing can vary by race, but the principle stays the same. Race inputs are locked before the race begins and cannot be changed afterward.
The deterministic model
Our fairness model is deterministic, which means the same inputs always produce the same output:
Result = f(EventLog, EngineVersion, Seed)
Seed: the locked randomness source
EngineVersion: the exact race engine version used
EventLog: the ordered list of race events (weather ticks, AI decisions, position updates, random usage)
If you replay the race with the same Seed, EngineVersion, and EventLog, you get the exact same finish order and timestamps.
The table below shows the architecture layers of our fairness system, from locking randomness before a race to independent verification after the race finishes.
Layer | Name | Timing | Responsibility |
1 | Commit Layer | Before race starts | Seal serverSecret with SHA256 commitment |
2 | Event Log Layer | During race | Record, hash, and chain every event |
3 | Reveal Layer | Immediately after race | Publish serverSecret + all plaintext payloads |
4 | Verification Layer | Any time after reveal | Independent audit and full replay |
Step 1: Race inputs are locked before the race
Before the race starts, we lock the “RaceLock” state, which includes:
All entries and placements
The selected pigeons and their attributes
The official weather snapshot used for the race
The race engine and rules version
A cryptographic commitment to race randomness
Blockchain anchor (timestamp proof)
At lock time, we store a cryptographic fingerprint of the RaceLock package on Polygon. This creates a public, timestamped record proving the inputs were locked before the race started.
Step 2: Randomness uses commit–reveal
If randomness is involved, we use a commit–reveal system to prevent rerolls and selective outcomes.
Commit phase (before the race)
We generate a secret value:
serverSecret = random(256-bit)
We publish only its fingerprint:
commitHash = SHA256(serverSecret)
The serverSecret is kept private until after the race. This locks the randomness upfront and prevents “try again until the preferred pigeon wins.”
Step 3: Weather is frozen and verifiable
Weather affects races, so we freeze it equally for everyone.
We capture a weather snapshot before the race using real-world conditions at that moment.
Weather is not live-polled during the race. The simulation uses the frozen snapshot.
The weather snapshot is included in the locked race data so any modification would be detectable.
Step 4: Every race event is logged and chained
We do not store “Bird A won” as the source of truth. Instead, we record the sequence of events that leads to the final state. This is called event sourcing.
Example event sequence:
seq=1 RACE_STARTED
seq=2 POSITION_UPDATED
seq=3 WEATHER_TICK
seq=4 RANDOM_CONSUMED
seq=5 POSITION_UPDATED
...
seq=N RACE_FINISHED
Tamper-evident event log
Each event is cryptographically sealed and linked to the previous event (hash chaining). If any single value is changed afterward, verification fails.
The event log uses hashes to bind data to the pre-race secret. Example schema includes:
payloadHash = HMAC_SHA256(serverSecret, canonical(payload))
prevEventHash and eventHash to chain events together
Canonical payload rules
To ensure replays are identical, payloads are canonicalized (standardized), for example with fixed key order and fixed float precision. This is what prevents silent changes to weather inputs, pigeon stats, AI decisions, or random number usage after the race.
Step 5: Reveal and verification after the race
After the race ends, we reveal the sealed data so anyone can verify it.
Reveal phase
After the race ends, we publish the serverSecret and the full plaintext payloads for every recorded event, so anyone can verify the outcome independently.
Verification process
Anyone can verify the race by:
Commit verification: check that
SHA256(serverSecret)matches the publishedcommitHashEvent verification: recompute payload hashes and validate the event hash chain
Race replay: load the exact EngineVersion, apply events in order, and confirm the final result matches
Verification tooling
We are building a dedicated verification tool so players can independently validate race outcomes.
Note: Race calculations run on game infrastructure for performance, but the inputs are locked and the outcome is designed to be verifiable through cryptographic proofs and deterministic replay.
