fix(proposer): canonical-descendant gate on rejected-buffer recovery exemption#497
Merged
spreston8 merged 1 commit intorust/stagingfrom May 2, 2026
Merged
Conversation
…exemption prepare_user_deploys exempts deploys in `rejected_in_scope` from the in-scope filter so genuinely rejected deploys can be re-proposed. Without a canonical-descendant gate, the exemption also fires when the rejection sits in a non-canonical sibling while the deploy's effects are already in canonical state — producing a recovery block that downstream validators correctly flag as `InvalidRepeatDeploy`. On FTT=0 shards this triggers mutual slashing. Mirror the validator-side `repeat_deploy` gate at the proposer: resolve the candidate sigs in batch and decline the exemption when status is `Finalized`. Resolver failure → decline conservatively. Tests: - validator-side defense regression (already passes pre-fix) - proposer-side gate (RED pre-fix, GREEN post-fix)
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.
Summary
prepare_user_deploysexempts deploys inrejected_in_scopefrom the in-scope filter so genuinely rejected deploys can be re-proposed. Without a canonical-descendant gate, the exemption also fires when the rejection sits in a non-canonical sibling while the deploy's effects are already in canonical state — producing a recovery block that downstream validators correctly flag asInvalidRepeatDeploy(the post-55cbbb06defense). On FTT=0 shards this triggers mutual slashing and a permanent split.The fix mirrors the validator-side
repeat_deploygate at the proposer: when a candidate sig is in bothdeploys_in_scopeandrejected_in_scope, resolve its finalization status viaresolve_batchand decline the exemption when status isFinalized. Resolver failure declines conservatively for the cycle (sigs retry next cycle).Tests
repeat_deploy_correctly_rejects_stale_recovery_when_d_is_finalized— validator-side defense regression. Passes pre- and post-fix; locks inValidate::repeat_deploybehavior so future changes can't silently regress it.proposer_must_skip_recovery_when_deploy_is_canonically_finalized— RED pre-fix, GREEN post-fix. Verified by stash/restore RED→GREEN sanity check.Verification
cargo test -p casper --test mod batch2::recovery_repeat_deploy_misfire_spec— 2/2 passtest_shard_degradation5/5 PASS via subprocess provider against the fixed binary (no flake, no cascade)Test plan
Co-Authored-By: Claude noreply@anthropic.com