Skip to content

hardening(frost/roast): verifiable blame — accuser quorum for exclusion; overflow can only park#4029

Merged
mswilkison merged 2 commits into
feat/frost-schnorr-migration-scaffoldfrom
hardening/roast-verifiable-blame-quorum-2026-06-11
Jun 11, 2026
Merged

hardening(frost/roast): verifiable blame — accuser quorum for exclusion; overflow can only park#4029
mswilkison merged 2 commits into
feat/frost-schnorr-migration-scaffoldfrom
hardening/roast-verifiable-blame-quorum-2026-06-11

Conversation

@mswilkison

Copy link
Copy Markdown
Contributor

Stacked on #3866 (base: feat/frost-schnorr-migration-scaffold). Implements item 2 of the review feedback on the FROST/ROAST stack (verifiable blame, not counted blame).

Problem

NextAttempt permanently excluded members on unverifiable observer counters — reject/conflict threshold 1, overflow 4 — summed across observers and across reasons, so a single byzantine observer fabricating counters could permanently exclude any honest member, and by repetition grind the included set below threshold (ErrAttemptInfeasible). That inverts ROAST's robustness guarantee: the design's whole point is liveness with t honest of n, and the blame layer handed a liveness-and-membership veto to any single member. Bundle evidence (OverflowEntry/RejectEntry/ConflictEntry) is observer-signed claims — nothing in a counter lets a third party re-check that the accused misbehaved.

What changed

Accuser-quorum gate (ExclusionAccuserQuorum). An accusation only produces action when made by at least f+1 = groupSize − threshold + 1 distinct credible observers (f = the byzantine tolerance). At f+1, at least one accuser is honest under the protocol's own t-of-n assumption, so the group may act as if the fault were verified. Real faults reach quorum naturally — contributions are broadcast, every honest member observes the same bytes — while f colluding members can never reach f+1 by fabrication. Production shape (n=100, t=51): quorum 50 vs. 49 worst-case byzantine.

Counting hygiene. Observers count once per accused per category regardless of claimed Count magnitude; reject reasons no longer multiply accusers; categories tally independently (reject + conflict claims no longer sum); only previous-IncludedSet members are credible accusers; accusations against non-original-set members are ignored.

Overflow can never be permanent. Transport pressure is observable only at the transport layer and can never be made self-incriminating. An established (quorum-corroborated) overflow accusation now parks the member for one attempt — same transient mechanics as silence parking — instead of excluding forever.

Sub-quorum claims are ignored entirely, not parked: acting on a single unverifiable claim would let one byzantine observer impose an attempt of liveness cost on any honest member at will.

Established reject/conflict accusations still exclude permanently, and the policy remains a pure deterministic function of (prev, bundle, threshold).

Why quorum rather than self-incriminating proofs now

The review's endgame is proof-carrying blame: the accused's own two operator-signed conflicting payloads (conflicts), or their signed contribution plus a re-checkable deterministic validation failure (rejects). That requires wire-format and verification-routine changes (the current bundle carries only counters). The quorum gate delivers the safety property — fabricated blame can never become permanent, and the grinding-to-infeasibility vector is closed — with no wire change, and is the correct floor even after proofs land (proof-verified entries can then bypass the quorum per category). RFC-21 Layer B now documents the policy, the rationale, and that roadmap; the residual cost (sub-quorum-observed faults burn retry attempts instead of excluding) is explicitly folded into the serial-attempt latency budget.

Tests

New regression coverage: quorum boundary at f vs f+1 for both permanent categories; fabricated-blame grinding across six attempts (single byzantine accuser, max counters, honest members never move); count-magnitude fabrication; cross-category non-summing; reason non-multiplication; non-credible accusers; non-original accused; established-overflow park-and-reinstate cycle; production-shape quorum pin (100, 51) = 50. Existing overflow/categories/soak tests updated to the new semantics. go test ./pkg/frost/... ./pkg/tbtc/... passes; go vet clean.

🤖 Generated with Claude Code

…w can only park

The NextAttempt exclusion policy permanently excluded members on
unverifiable observer counters: reject/conflict threshold 1, overflow
4, summed across observers and categories so a single byzantine
observer could fabricate evidence and grind honest members out of the
included set toward ErrAttemptInfeasible -- inverting ROAST's
robustness guarantee.

Bundle evidence entries are observer-signed claims, not
self-incriminating proofs, so the policy now refuses to take
permanent action on any accusation that is not group-established:

- ExclusionAccuserQuorum(groupSize, threshold) = f+1 distinct
  accusers, where f = groupSize - threshold is the byzantine
  tolerance. At f+1 at least one accuser is honest under the
  protocol's own t-of-n assumption. Real faults reach the quorum
  naturally because contributions are broadcast and every honest
  member observes them; fabricated ones cannot.
- Accusers are counted distinctly (one per observer per accused per
  category); claimed count magnitudes are no longer summed into
  blame. Reject reasons no longer multiply accusers, and categories
  are tallied independently instead of summing into each other.
- Only members of the previous IncludedSet are credible accusers;
  accusations against members outside the original signer set are
  ignored.
- Established overflow accusations (transport-blamable) now park
  transiently instead of excluding permanently: transport pressure
  can never be made self-incriminating, so it may cost an attempt of
  liveness but not permanence.
- Established reject/conflict accusations still exclude permanently.
- Sub-quorum claims are ignored entirely so a single byzantine
  observer cannot even impose parking liveness costs.

RFC-21 Layer B is updated to match, including the verifiability
roadmap: once the wire format carries self-incriminating proof (the
accused's own signed conflicting bytes; a re-checkable invalid
contribution), single-proof exclusion becomes sound and the quorum
gate can be relaxed per category.

New regression coverage: quorum boundary at f vs f+1 for both
permanent categories, fabricated-blame grinding across six attempts,
count-magnitude fabrication, cross-category non-summing, non-credible
accusers, non-original accused, established-overflow park-and-
reinstate cycle, and the production-shape quorum pin (100, 51) = 50.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: db9c3dff-1e8d-4d3a-8f79-de186e356d0c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hardening/roast-verifiable-blame-quorum-2026-06-11

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 and usage tips.

…g scope

Review follow-ups on the verifiable-blame revision:

- Fix inverted group-shape wording (51-of-100, not 100-of-51).
- State explicitly that near the assumption boundary the accuser
  quorum needs all but 2t-n-1 honest observers (50 of 51 at the
  production shape), so in the high-f regime the gate is a
  fabrication firewall rather than a working exclusion mechanism;
  proof-carrying blame restores exclusion there.
- Document the n-of-n edge of ExclusionAccuserQuorum (quorum 1,
  consistent with f = 0 under that shape's own assumption).
- Make precise that silence parking keys on bundle absence: a member
  that submits its evidence snapshot while withholding its signing
  contribution is not parked by this layer; that cost is bounded by
  the Annex B retry budget until t-of-included finalize.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mswilkison mswilkison merged commit 5fa67b1 into feat/frost-schnorr-migration-scaffold Jun 11, 2026
16 checks passed
@mswilkison mswilkison deleted the hardening/roast-verifiable-blame-quorum-2026-06-11 branch June 11, 2026 23:11
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