Skip to content

id: mutual-concession match attestation PoC on tic-tac-toe (#2248) - #2854

Merged
dezren39 merged 1 commit into
mainfrom
queue/3953-2248-attestation-poc
Oct 30, 2026
Merged

dezren39 merged 1 commit into
mainfrom
queue/3953-2248-attestation-poc

Conversation

@dezren39

@dezren39 dezren39 commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

PoC for #2248 (queue task 3953), implementing the #2037 mutual-concession attestation shapes on the tic-tac-toe example. Proof of concept only — no production attestation feature is claimed or built here.

Object shapes (new pkgs/id/src/attestation.rs, additive)

  • Genesis agreement — one signed event per player, kind attestation.genesis, body {game_id, logic_hash, players, witness, objection_window_secs}. Both players sign the identical body; logic_hash is the hash of the example's main.roc. The witness slot is present and unused; the objection window is a parameter only (objection handling is id: investigate: match audit — netcode log format, replay validation, and cheating signals #2038/id: design: match attestation + audit v1 #2039, out of scope).
  • Result claim — one signed event per player, kind attestation.claim, body {agreement, outcome, final_state_hash, frontiers}: the agreement hash answered, the asserted outcome, the hash of the final game state (the board/plays/winner JSON the example publishes), and both chain frontiers.
  • Viewer — compute_state is a pure function of the objects (authors taken from signature-verified decoded events): no complete genesis pair or only one claim → Proposed; concurring claims → Agreed; differing claims → Disputed, never Agreed. A player claiming twice with different claims also computes Disputed.

Demonstration (pkgs/id/tests/attestation_poc.rs, 3 tests, green on the laptop)

  1. Offline-first: genesis pair + both claims are ingested into one event store that has talked to nobody; the viewer computes Agreed.
  2. Sync: a second store receives exactly the first store's applied event bytes plus the bodies those headers commit to, and computes the identical state over the identical event-id set. (The transport is the existing range sync's job; the PoC question is whether the object shapes carry the attestation, and the test says so explicitly.)
  3. Negative case: one claim names the wrong winner → Disputed.
  4. A single claim stays Proposed.

What this does not prove

Witness decisions, objections, audit replay, and fork-proof voiding of claims are untested here; bodies travel beside headers in the demonstration rather than through the content/blob layer; the viewer trusts chain::decode's signature verification and does not itself re-verify. Findings note with the full proved / did-not-prove list is on #2248.

Existing suites: the crate builds with no new warnings; clippy clean on the new files. Full pkgs/id CI on this PR is the gate for the existing event_store/chain suites.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@dezren39
dezren39 requested a review from a team as a code owner October 30, 2026 22:43
@coderabbitai

coderabbitai Bot commented Oct 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 18 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e49cf738-ca8b-4fd4-b7d8-d2b2206a82c8
Commits

Reviewing files that changed from the base of the PR and between b706a83 and f2633ac.

Files selected for processing: 3
  • pkgs/id/src/attestation.rs
  • pkgs/id/src/lib.rs
  • pkgs/id/tests/attestation_poc.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T22:45:51.823394Z f2633ac PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f2633ac94f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +86 to +87
/// As [`GenesisAgreement::body`].
pub fn agreement_hash(&self) -> Result<Hash, serde_json::Error> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include a match-specific identifier in the signed agreement

When the same players play another match with the same game logic, witness, and objection window, the agreement body—and therefore agreement_hash()—is identical. Claim association in compute_state uses only that hash, so previous claims can satisfy a new match before either player submits a new result, or turn both matches into Disputed when their outcomes differ. The documented game_id identifies the game, not the match. Include a jointly signed match identifier or nonce so claims cannot cross match boundaries.

Useful? React with 👍 / 👎.

Comment on lines +228 to +232
let genesis_ok = agreement.players.iter().all(|player| {
genesis
.iter()
.any(|(author, signed)| author == player && signed == agreement)
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject duplicate player identities before counting signatures

If an agreement contains players: [p, p], a single genesis signature passes both iterations of this check, and a single claim from p subsequently populates both per_player entries. The viewer therefore returns Agreed with only one signed claim, contrary to the two-player mutual-concession requirement and the documented single-claim behavior. Reject agreements whose two player identities are equal before evaluating genesis or claims.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant