Pawnshake v0.1.0 · draft

Protocol

Reports and storage

After a game, either player uploads its records. The server merges every upload, finds forks, replays the game and saves it. A finished game shrinks to about a kilobyte.

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[] }
  1. Verify. The genesis, every record, every receipt.
  2. 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.
  3. Look for forks. One signer, one seq, two different headers, or a record that contradicts its signer's heartbeat: the signer loses.
  4. Replay and store. Run the canonical order and save the result with its state.
Staying silent gains nothing. The winner received every record the loser sent, so the winner's report carries them.
Winner Server Loserreport: every record it holdsnever reportsthe winner's copy holds the loser's records too Winner Server Loserreport: every record it holdsnever reportsthe winner's copy holds the loser's records too

Records a player signed but never delivered or anchored did not happen, as far as the game is concerned.

Game states

StateWhenRated
finalended by a provable termination, a verdict, or both ENDsyes
pendingnot ended in the chain yet; waits for the other reportnot yet
disputeda DISPUTE record: a live time check failedno
canceledoutage beyond the budget without two RESUMEs, a CANCEL, or a leave the profile cancelsno
unfinishedstill 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.

Stored game
genesis ~650
records, no signatures ~1 KB seq, seen, at, op, args
white head sig 64 B
black head sig 64 B
verdicts signed
last receipt optional

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.