Reporting a game
When a device is online it uploads every game it played, automatically, both players, every time:
POST /pawnshake/v1/reports
{ genesis, records_white[], records_black[], records_server[], receipts[], beats[] }
- Verify. The genesis, every record, every receipt.
- Merge. With everything already held for this game: the union. A report can only add records, so leaving some out never removes what the other player or the anchors put there.
- Look for forks. One signer, one seq, two different headers, or a record that contradicts its signer's heartbeat: the signer loses.
- Replay and store. Run the canonical order and save the result with its state.
Records a player signed but never delivered or anchored did not happen, as far as the game is concerned.
Game states
| State | When | Rated |
|---|---|---|
final | ended by a provable termination, a verdict, or both ENDs | yes |
pending | not ended in the chain yet; waits for the other report | not yet |
disputed | a DISPUTE record: a live time check failed | no |
canceled | outage beyond the budget without two RESUMEs, a CANCEL, or a leave the profile cancels | no |
unfinished | still pending after the wait (WhitePawn: 7 days) | no |
Saving is idempotent on the genesis hash. Canceled, disputed and unfinished games are saved too, without ratings: PGN result * and the state as termination.
The compact form
Until a game is final, every record keeps its signature: any of them could become fork evidence. Once it is final, everyone keeps a compact form instead.
A 40-move game (80 moves, 80 ACKs, 2 ENDs, a verdict) is about 1 KB of records plus 3 signatures, against about 10 KB of signatures alone if every record kept its own.
Nothing is lost. A verifier rebuilds every body and header from the genesis forward (prev, seen_hash, ply, legal) and checks only the two head signatures. Changing, adding or dropping any earlier record changes the chain of record ids, and a head signature fails. That is the same reason one head is enough for an anchor.