-
Notifications
You must be signed in to change notification settings - Fork 10
Game Channels
This page is a conceptual overview of game channels — Xaya's technology for running real-time, millisecond-paced gameplay off-chain while keeping every blockchain guarantee about fairness and ownership. You'll learn what problem channels solve, how the open/play/close lifecycle works, why cheating and stalling don't pay, and when you actually need a channel versus plain on-chain moves.
Note: This is an overview only. A full, hands-on game-channels tutorial is planned for this wiki later. Until then, the reference is the
gamechannellibrary inside libxayagame and the XayaShips sources.
On Polygon, a Xaya move is an ordinary transaction (see Names and Moves). That's great for most games:
- Blocks arrive roughly every ~2 seconds.
- A move costs well under $0.01 in gas.
For a strategy game, an MMO-style world, or anything turn-based and asynchronous — like the mover game from the tutorial — that's plenty. But now imagine a head-to-head shooter, a racing game, or even battleships played at a brisk pace. Players act several times per second. Pushing every one of those actions through the chain would mean:
- Latency: ~2 seconds minimum before your opponent's GSP even sees your move.
- Cost: fractions of a cent add up fast at 10 inputs per second per player.
- Noise: thousands of micro-moves bloating the chain for a single match.
Real-time games need millisecond round-trips. The chain can't provide that — and it doesn't have to.
A game channel is a private fast lane between two players. Instead of sending every move to the blockchain, the players:
- Open a channel with a normal on-chain move (and the opponent joins the same way).
- Play by exchanging signed state updates directly with each other over a fast off-chain connection — as fast as their network allows. No blocks, no gas, no waiting.
- Close the channel with one final on-chain move that carries the signed outcome.
The blockchain only ever sees three kinds of events: channel open/join, channel close, and (rarely) disputes. Everything in between — every shot, every turn of the wheel, every volley — happens off-chain in milliseconds.
sequenceDiagram
participant A as Player A
participant B as Player B
participant Chain as Polygon (on-chain moves)
participant GSP as GSP (referee)
A->>Chain: Open channel
B->>Chain: Join channel
Chain->>GSP: Channel exists in game state
Note over A,B: Off-chain play — millisecond round-trips, zero gas
loop For the whole match
A->>B: Signed state update
B->>A: Signed state update
end
A->>Chain: Close channel (final signed state)
Chain->>GSP: Close move delivered
GSP->>GSP: Verify signatures, replay rules, settle result
The result of the match (who won, win/loss tallies, whatever your game tracks) flows back into the regular game state, where your GSP processes it like any other move and serves it over the usual JSON-RPC interface.
If the moves never touch the chain, what stops someone from claiming a win they didn't earn? The answer is the same thing that secures all of Xaya: deterministic, replayable rules (see Blockchain Gaming Basics).
- Every off-chain state update is cryptographically signed by the player who made it.
- The accumulated chain of signed updates forms a state proof: "starting from the agreed initial state, these signed moves lead to this state."
- When a channel closes (or a dispute happens), the GSP — using libxayagame's
gamechannellibrary — verifies the state proof on the chain's behalf: it checks every signature and replays the moves through the exact same deterministic C++ game rules that govern the rest of the game.
A forged state simply doesn't verify. Your opponent can't claim a position your shared rules can't produce, and they can't fake your signature on a move you never made. The chain stays the final arbiter; it just doesn't have to watch every move to do its job.
Cheating isn't the only attack — what if your opponent simply stops responding the moment they start losing? Channels handle this with an on-chain dispute mechanism:
- You file a dispute by putting your latest signed state proof on-chain (an ordinary move).
- The GSP verifies your proof and starts a timeout, measured in blocks.
- Your opponent must answer with a newer valid signed state before the timeout expires — proving the game actually moved on past the state you submitted.
- If they can't or won't, they lose by timeout and the channel is closed in your favor.
sequenceDiagram
participant A as Player A (honest)
participant B as Player B (stalling)
participant Chain as Polygon
participant GSP as GSP (referee)
A->>B: Signed state update
Note over B: ...silence...
A->>Chain: Dispute (latest signed state proof)
Chain->>GSP: Dispute move delivered
GSP->>GSP: Verify proof, start block timeout
alt B answers in time
B->>Chain: Resolution (a newer signed state)
Note over A,B: Play continues — or the newer state settles the match
else Timeout expires
GSP->>GSP: B forfeits — channel closed in A's favor
end
The incentives line up neatly: an honest, online player can always answer a dispute, because they always hold the newest mutually signed state. Only a staller or a cheater gets caught by the timeout. In practice disputes are rare — they're the fallback, not the normal flow. A normal match ends with the winner submitting the final signed state and the channel closing cleanly.
Most Xaya games don't. Plain on-chain moves are simpler to build and operate, and at ~2-second blocks and sub-cent fees they cover a lot of ground.
| Use plain on-chain moves when... | Use a game channel when... |
|---|---|
| Gameplay is turn-based or asynchronous | Gameplay is real-time or fast back-and-forth |
| Many players share one world (MMO-style) | Exactly two players compete head-to-head |
| A move every few seconds (or minutes) is fine | Players act multiple times per second |
| Examples: mover, strategy, world games | Examples: battleships, racing, shooters |
A good rule of thumb: start on-chain. If your game is a 1v1 competitive match where 2-second latency would ruin the experience, that's when channels earn their extra complexity. The two approaches also combine naturally — XayaShips keeps its lobby (the list of open channels) and each player's win/loss record in the regular on-chain game state, and only the matches themselves run inside channels.
Game channels aren't theoretical — they run in production today:
- XayaShips — a full battleships game, live on Polygon. Channel opens, closes, and disputes are regular Xaya moves; matches play out off-chain; the GSP settles results into on-chain stats. It's the canonical reference implementation.
- Real-time racing demo — a head-to-head racing game built on the same channel stack, demonstrating smooth, continuous real-time play (not just discrete turns) over signed off-chain updates.
- First-person shooter demo — a 1v1 FPS using the same approach: players exchange only signed inputs, and the shared deterministic engine computes positions, hits, and scores — so a hacked client can't change the verified outcome.
The racing and FPS demos show the surprising part: even twitch-action games fit the model, because the protocol only needs to order and sign player inputs — the deterministic rules do the rest.
To make the lifecycle concrete, here is how the battleships game actually wires channels into a GSP. Everything below comes straight from the ships sources (ships/logic.cpp).
The on-chain move set is tiny. Every ships move is a regular Xaya move ({"g":{"<ships-game-id>":{...}}}), and the GSP dispatches on six single-letter keys:
| Key | Move | What the GSP does |
|---|---|---|
c |
create channel | Records a new channel with one participant; the channel ID is derived from the move's unique ID |
j |
join channel | Adds the second participant; the match can begin off-chain |
a |
abort channel | Creator cancels a channel nobody joined |
l |
declare loss | A player concedes; the GSP credits the opponent's win without needing any proof — conceding against yourself needs no verification |
d |
dispute | Submits a signed state proof; the GSP verifies it (signatures + replaying the board rules) and starts the block timeout |
r |
resolution | Answers a dispute with a newer valid state proof |
That's the entire on-chain protocol. Note the asymmetry: the happy path for ending a match is l — the loser declares the loss (their client does it automatically when the game ends), which needs no state proof at all. Disputes and resolutions, with their full cryptographic verification, only come out when the players disagree.
The regular game state still does the boring work. Alongside channels, the ships GSP keeps ordinary SQLite state: the list of open channels (the lobby) and per-name win/loss stats — all served over the standard RPC interface like any other game. The GSP also auto-deletes channels that sit half-open (one participant) for too many blocks, so the lobby doesn't fill with abandoned matches.
The board rules are the consensus. The actual battleships logic — ship placement, shots, hits, victory — lives in C++ classes that implement the gamechannel library's board-rules interface. The same compiled rules run in two places: in each player's client to play the match, and in every GSP to verify state proofs when a dispute arrives. That's the trick that makes off-chain play safe: the referee and the players are running literally the same deterministic code, so a state that didn't come from legal play cannot verify anywhere.
If you're considering a channel game of your own, read ships/logic.cpp top to bottom with the table above in hand — it's the clearest map of how little on-chain surface a channel game actually needs.
-
gamechannel/in libxayagame — the C++ library that implements the channel protocol: signed state transitions, state-proof verification, dispute/resolution handling, and the glue to run it inside a GSP. -
XayaShips — a complete, working game built on it (the
ships/directory in the same repository), from channel lifecycle moves to on-chain settlement.
If you want to peek ahead, those two codebases are the best material available today.
A complete game-channels tutorial — building a channel game step by step, the way the mover tutorial does for on-chain games — is planned for this wiki later. In the meantime:
- Make sure you're comfortable with the on-chain foundation first: Xaya Architecture, What Makes a GSP, and the mover tutorial.
- Unsure about a term? Check the Glossary.
Xaya developer documentation — verified on Polygon mainnet. Questions? Xaya Development Discord