-
Notifications
You must be signed in to change notification settings - Fork 58
Slashing Penalty Calculation Race Under Concurrent Validator Set Changes #32
Copy link
Copy link
Closed
Labels
Complexity: HardcoreExtremely difficult, high-complexity engineering taskExtremely difficult, high-complexity engineering taskGrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSLayer: Core-EngineCore engine layerCore engine layerMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignCampaign: Official CampaignType: Race-ConditionConcurrency and race condition related issuesConcurrency and race condition related issues
Description
Activity
Metadata
Metadata
Assignees
Labels
Complexity: HardcoreExtremely difficult, high-complexity engineering taskExtremely difficult, high-complexity engineering taskGrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSLayer: Core-EngineCore engine layerCore engine layerMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignCampaign: Official CampaignType: Race-ConditionConcurrency and race condition related issuesConcurrency and race condition related issues
Slashing Penalty Calculation Race Under Concurrent Validator Set Changes
Problem Statement
The slashing penalty calculator in
src/slashing/penaltyCalculator.tscomputes the penalty amount for a slashed node based on the current active validator set size. ThecalculatePenalty()function at line 75 readsactiveValidatorCountfrom the database and computespenalty = basePenalty * (1 + (totalValidators - activeValidators) / totalValidators). When a validator joins or leaves the active set concurrently with a slashing event (e.g., validator A joins while validator B is being slashed), the slashing event may read the validator count BEFORE the join (10 validators) while the join completes AFTER the penalty calculation writes. The penalty is computed for 10 validators but the actual active set is now 11. If the penalty formula penalizes nodes more heavily when fewer validators are active (to incentivize participation), the node is over-penalized by 10%.State Invariants & Parameters
1 + (total - active) / total(range [1.0, 2.0])penalty == f(active_validator_count_at_slashing_time)Affected Code Paths
src/slashing/penaltyCalculator.ts:70-110— Read-count-then-calculate racesrc/staking/validatorRegistry.ts:45-75— Validator set changessrc/slashing/executor.ts:55-85— Slashing execution pipelineResolution Blueprint
SELECT COUNT(*) FROM active_validatorsandINSERT INTO slashing_events (...) VALUES (...)in a singleSERIALIZABLEtransaction. This ensures the count is consistent with the moment of slashing.validatorCountAtSlashingas a field in theslashing_eventstable, so the penalty is always computed from the count at the time of the event, not the current live count.SHARE ROW EXCLUSIVElock on thevalidator_registrytable before computing the penalty, preventing concurrent validator set changes during the calculation.Labels
Complexity: HardcoreLayer: Core-EngineType: Race-Condition