Skip to content

Show casts from keys revoked since; strict hex and base64 in message checks - #17

Merged
Spider333 merged 1 commit into
mainfrom
fix/removed-keys
Oct 24, 2026
Merged

Spider333 merged 1 commit into
mainfrom
fix/removed-keys

Conversation

@Spider333

@Spider333 Spider333 commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Outpost assumed that when a key is removed, the network deletes what it signed. Since Snapchain engine V14 it does not (engine.rs should_revoke_signer, version.rs:303; a gasless KEY_REMOVE deletes only the key record, gasless_key_merge.rs). So the client reported genuine old casts as forgeries: every cast signed by a key someone revoked since, including keys revoked with ./outpost uninstall, showed up as "signed by a key that is not the author's".

Draft. David decided on 23 Oct: merge after the prize deadline (Sat 24 Oct 14:47 UTC), together with #15. Before merging: mark ready, CI green. It merges cleanly with #15 in either order. Merging to main redeploys the hosted client on GitHub Pages.

What changes

  • Onchain key removed since (Optimism's KeyRegistry says it was the author's): the cast is shown, marked "key revoked since". New key check revoked.
  • Gasless key the second node does not list: Snapchain's HTTP API cannot tell a key revoked since from a key that was never the author's, so the cast is held back like an unverified one and counted as "not listed: revoked since, or not the author's", not as a failure. "Show them anyway" shows it marked "key not listed". New key check unlisted.
  • Provably not the author's key (the node claims onchain, Optimism says no): unchanged, dropped and counted as a failure.
  • Web and CLI tags, the verifier summary, and the outdated comments in verify.ts and secondnode.ts.

Trade-off: a node that forges a cast with a made-up gasless key is now reported as "not listed" rather than "failed verification". The forged cast is still never shown unless the reader asks, and then it is marked.

Encoding leniencies (reported by a blind verifier on PR #15)

  • Hex fields: viem's hexToBytes skips the first two characters without checking them, so 1x… decoded like 0x…, and upper case read like lower case. Now only 0x plus lower-case hex passes (hash, signer and cast ids). Snapchain writes lower case.
  • Signature: atob ignores the unused bits of the last base64 character, so another spelling of the same bytes passed. Now only the canonical spelling passes.
  • Renamed null fields: left as is, with the reason in the code at extraField. Honest nodes send null fields the rebuilt message does not have, and a null carries nothing signed or shown; tightening it would reject honest data.

Known limit, now in the README: Optimism records no removal time and a cast's date is signed by its own key, so a cast backdated with a leaked, removed onchain key and served by a dishonest node would show, marked "key revoked since". Honest nodes refuse such casts.

None of the three changed signed content; real mainnet fixtures still verify. Not covered: a cast delete's targetHash is still decoded through MessageData.fromJSON, which reads base64 loosely (no delete message in the fixtures to test against).

Tests

npm test 72 pass (2 new, 3 updated to the new outcomes), tsc strict plus --noUnusedLocals --noUnusedParameters clean, build clean, jscpd 0 clones. Blind verify round 1: FAIL (the null-field reason was only in this text, not the code; hex case was still lenient), both fixed; round 2: PASS (154 changed copies of real messages all rejected, all 7 fixtures verify, key checks as described). Merged locally with feat/society-votes (PR #15): no conflicts, 93 tests pass, so either can go first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ut7NR5KyubX7WMMggTFNEb

Since Snapchain engine V14 a removed key's earlier messages stay on the
network, but the client treated them as forgeries: every cast signed by a
key revoked since (with ./outpost uninstall, for one) was reported as
"signed by a key that is not the author's".

- onchain key removed since: shown, marked "key revoked since" (Optimism
  shows it was the author's)
- gasless key the second node does not list: held back and counted as
  "not listed: revoked since, or not the author's", not as a failure,
  because the HTTP API cannot tell the two apart
- a key the node calls onchain that Optimism does not list: still dropped

Message checks now accept only 0x lower-case hex (hash, signer, cast ids)
and canonical base64 signatures. Null fields stay ignored, with the
reason at extraField. README states the limits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ut7NR5KyubX7WMMggTFNEb
@coderabbitai

coderabbitai Bot commented Oct 23, 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 59 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: 910de80b-8ba4-4f51-b42b-994854721acb
Commits

Reviewing files that changed from the base of the PR and between 79eb20a and b60f98c.

Files selected for processing: 6
  • README.md
  • src/cli/main.ts
  • src/core/secondnode.ts
  • src/core/verify.ts
  • src/web/app.ts
  • test/verify.test.ts
  • 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.

@Spider333
Spider333 marked this pull request as ready for review October 24, 2026 18:10
@Spider333
Spider333 merged commit cb784ab into main Oct 24, 2026
1 of 2 checks passed
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