feat(frost): wire interactive share-verification blame into the bundle (7.3 share-blame)#4091
Merged
mswilkison merged 1 commit intoJun 19, 2026
Conversation
…e (7.3 share-blame) The blame layer (PR2b-2) excluded members for coarse f+1 evidence (2a) and coordinator equivocation (2b), but an interactive bad-share submitter escaped blame entirely: the engine's InteractiveAggregate surfaces candidate culprits in a typed InteractiveAggregateShareVerificationError, yet the runner just wrapped and returned the error, dropping them. EngineRound2ShareVerifier and Round2Collector.ClassifyCandidate- Culprits were both complete but constructed/called nowhere -- so a member that submitted an invalid FROST signature share was never excluded and the retry could loop. Wire the third fault source on the interactive failure path (mirroring 2b): on a runner.Run share-verification failure, driveInteractiveRoastSigningIfEnabled type-asserts the engine to Round2ShareVerifyingEngine, converts the engine's uint16 candidates to MemberIndex (dropping 0 / out-of-range so a malformed candidate can never truncate into an honest seat), builds an EngineRound2ShareVerifier bound to the attempt, classifies each candidate's RETAINED share via ClassifyCandidateCulprits (frozen-Q1 boundary: only an ACCEPTED retained share that re-verifies INVALID is blamed; every not-the-member's- fault condition fails closed), and stashes the resulting reject accusations in the same union pending-evidence entry as the 2b proofs. BroadcastForcedSnapshot carries them; computeNextAttempt's f+1 reject gate excludes an f+1-corroborated bad-share member. f+1, not instant: a share is self-incriminating only against the package THIS observer accepted, so a byzantine coordinator's targeted split could otherwise make one honest observer instant-exclude an honest peer; f+1 corroboration (honest observers re-verify identical retained bytes deterministically) closes that. Best-effort + fail-safe: a non-share error, a verifier-incapable engine, malformed candidates, or an empty classification all stash nothing. Compile-time assertion that the cgo engine satisfies Round2ShareVerifyingEngine; the stale "evidence/proofs mutually exclusive" comments are corrected (one interactive failure now carries both). Design locked via Codex + Gemini consult (both PROCEED, no holes). Prod-dormant until the cgo interactive engine is registered (gated on the frost-secp256k1-tr audit). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
0f6e5f9
into
feat/frost-schnorr-migration-scaffold
15 of 16 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RFC-21 Phase 7.3 — interactive share-verification blame (the third fault source)
Follows PR2b-2 (the blame layer: 2a #4088 coarse f+1 evidence, 2b #4089 coordinator-equivocation proofs, 2c #4090 tests). This closes the last blame gap.
The gap
The blame layer excluded members for coarse faults and coordinator equivocation, but an interactive bad-share submitter escaped blame entirely. The engine's
InteractiveAggregatesurfaces candidate culprits in a typedInteractiveAggregateShareVerificationError{CandidateCulprits []uint16}, yet the runner just wrapped and returned the error, dropping them.EngineRound2ShareVerifierandRound2Collector.ClassifyCandidateCulpritswere both complete but constructed/called nowhere — so a member that submitted an invalid FROST signature share was never excluded and the retry could loop.The wiring
On a
runner.Runshare-verification failure,driveInteractiveRoastSigningIfEnabled(where 2b already extracts proofs):errors.Asthe typed*InteractiveAggregateShareVerificationError(through the runner's%wwrap);uint16candidates →MemberIndex, dropping0/ out-of-range so a malformed candidate can't truncate into an honest seat;Round2ShareVerifyingEngine(skip if absent — still stash 2b proofs);EngineRound2ShareVerifierbound to the attempt (SessionID == active.SessionID(),AttemptContextHash,TaprootMerkleRoot);ClassifyCandidateCulpritsre-verifies each candidate's retained share (frozen-Q1 boundary: only an ACCEPTED retained share that re-verifies INVALID is blamed; every not-the-member's-fault condition fails closed);BroadcastForcedSnapshotcarries them;computeNextAttempt's f+1 reject gate excludes an f+1-corroborated bad-share member.Why f+1 (not instant)
A share is self-incriminating only against the package this observer accepted — a byzantine coordinator's targeted split could otherwise make one honest observer instant-exclude an honest peer. f+1 corroboration (honest observers re-verify identical retained bytes deterministically) closes that. Only unforgeable coordinator-equivocation proofs (2b) are instant.
Safety
Best-effort + fail-safe: a non-share error, a verifier-incapable engine, malformed candidates, or an empty classification all stash nothing.
EngineRound2ShareVerifieralready fails closed against false blame (bound-attempt / root / submitter / package-body checks). Compile-time assertion that the cgo engine satisfiesRound2ShareVerifyingEngine. Stale "evidence/proofs mutually exclusive" comments corrected (one interactive failure now carries both).Scope / gating
Prod-dormant until the cgo interactive engine is registered (gated on the
frost-secp256k1-traudit).Verification
frost_native/frost_roast_retry/frost_native frost_roast_retry/frost_native frost_tbtc_signerw/ CGO)-race; gofmt clean🤖 Generated with Claude Code