Play the game

paros play is the interactive half of this book. It runs the real paros-core state machine in your browser, compiled to WebAssembly. It hands you the two things a distributed system never lets you hold: the network and the clock.

What the game is

You choose which in-flight message lands next. You choose which message is dropped or duplicated, which node ticks, who crashes, when it restarts, and what a client proposes. There is no latency model and no random scheduler. A partition is a message you decline to deliver, and a slow node is a node you decline to tick.

When a node must answer, you answer for it. Promise or Nack? Which value goes in the Accept? Re-propose the slot the quorum reported, fill the hole with a no-op, or open a fresh slot? Serve the read or wait? The game asks, and the core judges:

  • A right answer is what the real role does, so the real node steps and the world advances.
  • A wrong answer does not enter the core. The world does not take the bad branch. The game explains the violation that the answer causes, with this prompt's own ballots and values, and the level records the mistake. No toy "wrong acceptor" exists anywhere in the game. paros-core is never forked and never buggified, exactly as the rest of the project treats it.

You play a role until you get it right, and that is how you stop playing it. Pass the level that teaches a role and you unlock automation of that role in every later level. Acceptor replies, the P2c value selection, the apply walk and heartbeat delivery each become a toggle that you earn. The levels get shorter as the protocol gets larger, so by Act II you drive a leader instead of clicking every Promise.

How a level works

Every level is the same five things:

  • Briefing — a short statement of the world you enter and why it is interesting. This is the mechanism prose that used to sit in the chapters.
  • Goal — a predicate over the world, evaluated after every action: a value is chosen, chosen_gap() is None, the client's read watermark never regressed. It is Open, Reached, or Failed with a reason.
  • Prompt — the role question, with the node's own relevant state and the choices. The state includes its promised ballot, its accepted record for the slot, and what the Promises reported. Answer the prompt and the core says whether you are right.
  • Undo — the engine keeps your action log and rebuilds the world by replay. The core is deterministic and draws no randomness, so undo is exact. There is no hidden state to restore and no seed to roll again.
  • Hints and automation — a hint appears after a mistake or two. The automation toggles you have unlocked sit beside the stage. A level pins one off when it needs you to do that part by hand.

The stage derives its state from the world on every change, and animates nothing on its own. You see the node ballots and roles, and the accepted log as a column of slot boxes: green for chosen, red for a hole, grey for undecided. You also see the election arc that fills with ticks, and the in-flight queue as clickable dots on the wire.

The level map

Act I is single-decree Paxos: three acceptors, one or two proposers, one slot, no clock and no storage. Act II is the replicated log: three ColocatedNodes, a client, and disks that survive a crash. Act III adds truncation, the trim-point jump and a second client. Act IV adds the quorum systems, the matchmaker plane, disk faults and a wipe.

LevelWhat you do by handWhat it teachesField guide
act1/choose-a-valueDeliver Prepare, Promise, Accept, Accepted one message at a time, with one acceptor silentThe two phases, and why two of three is enoughHow Paxos chooses one value
act1/be-the-acceptorAnswer every Prepare and every Accept yourselfThe promise rule (>) and the vote rule (>=) — the whole of the acceptorHow Paxos chooses one value
act1/adopt-the-valueChoose which value a second proposer puts in its AcceptP2c: a Promise that reports a value takes the proposer's own choice awayWhy one value is safe
act1/the-duelRun two proposers against each other and still get a value chosenLivelock is a liveness failure and never a safety oneHow Paxos chooses one value
act1/quorum-intersectionPick the Phase-1 and Phase-2 reach sets yourself, and try to dodge the overlapEvery Phase-1 quorum meets every Phase-2 quorum; the pivot acceptor is unavoidableWhy one value is safe
act1/recovery-is-not-catch-upAdopt a value that exactly one acceptor ever accepted and nothing choseRecovery repairs an invariant, not data: it fires when nothing was chosenWhy one value is safe
act2/persist-before-sendOrder a Ready batch's writes and messages, then crash at each seamA Promise or Accepted sent before its write is durable can un-make a decisionCrash and restart safety
act2/a-log-of-decisionsDeliver slot 3's Accepted before slot 2's, then decide what may applySlots are chosen out of order and applied in order: chosen_index is a contiguous prefixFrom one value to a log
act2/elect-a-leaderTick a follower to its timeout and drive one Prepare over the whole log suffixPhase 1 once per leadership, and the recovery duty before any new workThe stable leader
act2/steady-stateDeliver the Accepts, Accepteds and Heartbeats for a stream of commandsOne round trip per command, pipelining, and the commit index piggybacked on the beatThe stable leader
act2/the-permanent-gapDrop exactly slot 1's Accepts, let slot 2 be chosen, crash the leader, then fill the holeA slot no Promise reports wedges the whole cluster forever unless the new leader fills itThe stable leader
act2/what-survives-a-crashCrash and restart at each step of a decision, and say what the durable record keepsA chosen value must overwrite a stale lower-ballot accept, or a restart resurrects itCrash and restart safety
act2/the-read-that-liesAsk a follower that missed a leader change for a read, and decide if it can answer nowA node cannot know its log is current; a read asks a Phase-1 quorum how far to readWhy reads are not free
act3/truncate-by-consensusAsk the leader to compact and watch each node move its own floor when its walk reaches the slotThe floor is a decided control command, so one decision gives one cluster-wide floorTruncation and the trim point
act3/the-stranded-nodeStrand a node below the floor, let a peer answer its catch-up with the trim point, and state its promise after the jumpA trim-point jump moves the floor and never a promise: the node keeps the promise it hadTruncation and the trim point
act3/the-fresh-leader-trapHold a read at a new leader while the slot that it inherited is not decided againA vote raises the watermark before the slot is chosen, so the read waits for itWhy reads are not free
act3/linearizable-or-notProduce a history with a read across a leader change, then try to break itLinearizability as three conditions over the client's own program orderWhy reads are not free
act3/chosen-is-not-appliedAnswer a client retry for a slot that is chosen above a hole, twiceChosen is a fact about the cluster; applied is a fact about this nodeWhy reads are not free
act4/flexible-quorumsPick each phase's reach over four acceptors, with q1 = 3 and q2 = 2q1 + q2 > n: the intersection that matters is between the phases, not inside oneBeyond Multi-Paxos
act4/the-gridDecide two slots on two columns, then send a stray Accept outside a slot's columnA row elects and a column decides; a vote outside the column counts for nothingBeyond Multi-Paxos
act4/quorum-readsServe a read at a follower from a row's vote watermarks, and hold one that is not coveredA linearizable read with no leader and no clock, paid for by waitingBeyond Multi-Paxos
act4/the-handoffHand the leadership on under the same ballot, then try to hand it on againSame ballot, no Phase 1, gap filling off, and one hop onlyBeyond Multi-Paxos
act4/matchmakingRegister a campaign, read the histories back, and close Phase 1 over each configurationPhase 1 needs a quorum of every configuration in H_b, not a quorum of the unionBeyond Multi-Paxos
act4/reconfigureGrow the acceptor set onto a spare and get a command chosen under itA reconfiguration is a round change; a removed node still answers Phase 1Beyond Multi-Paxos
act4/garbage-collectionRaise the watermark, then retire a removed acceptor with the evidence in handInstalled is not collected, and a retire request must carry the effective watermarkBeyond Multi-Paxos
act4/matchmaker-generationsReplace the matchmaker set: stop, reconstruct, bootstrap, decide, publishThe successor set is decided by single-decree Paxos over the old setBeyond Multi-Paxos
act4/faulty-recordsDamage one accepted record, then put each Promise that arrives into its CTRL case"I no longer know" is a third answer, and it must not become "I did not vote"Beyond Multi-Paxos
act4/the-wiped-nodeErase a disk, take the library's refusal, and keep the survivors decidingA lost promise cannot be restored, so the library refuses the bootBeyond Multi-Paxos

Level ids are stable strings, never indices, and a level opens directly at play/#<id>.

What comes next

The four acts cover what paros implements today, with one exception. Compartmentalized Paxos's proxy leaders are in the core and have a chapter, and no level yet: their driver is the next half of that work. The separate replica tier is not in the crate, so it has neither. The rule holds for both halves of this book. A mechanism gets a level when the core can play it for real.

Correctness itself is not proven in the browser. The game runs one world that you schedule by hand, and it draws no randomness at all. The deterministic simulation is where paros proves its claims, over thousands of seeded runs with network faults, crashes and storage faults. Every chapter's "Proven, not asserted" section reports what that simulation holds.

How this book relates to it

The levels teach the mechanism. The chapters are the field guide beside them: the papers a rule comes from, the proof structure, the doctrine, and the map from each protocol name onto the real symbol in paros-core. A chapter does not re-walk an interleaving that a level plays. It states the mechanism in a paragraph and links you to the level that makes you do it.

Open the game.

Found an error or it needs a clarification? Open an issue on GitHub.
Substantiated corrections will be incorporated with attribution.