Problem Statement / Feature Objective
The slashing condition engine maintains a bitfield accumulator tracking slashing events per validator for MAX_HISTORICAL_EPOCHS = 2^12 epochs. When the current epoch counter wraps past u16::MAX (65535), the accumulator indexing produces an out-of-bounds read or a silent wrap, allowing a previously-slashed validator to escape detection and re-participate.
Technical Invariants & Bounds
- SLASHING_HISTORICAL_WINDOW = 4096 epochs (~18.2 days at 6.4 min/epoch).
- Accumulator stored as BitVec of length (MAX_VALIDATORS * WINDOW) / 8 bytes.
- Epoch counter is u64, but indexing uses (epoch % WINDOW) as u16.
- Wrap occurs when epoch >> 12 increments after 2^16 total epochs (~2.9 years).
- A double-vote or surround-vote evidence older than the rollover is treated as fresh.
Codebase Navigation Guide
- src/slashing/accumulator.rs - SlashingAccumulator with record_slashing() and check_slashed().
- src/slashing/condition-engine.rs - top-level slashing evaluation loop.
- src/slashing/types.rs - SlashingEvent and SlashingStatus enums.
- src/db/slashing-store.rs - persistent storage of accumulator state.
- tests/slashing/accumulator_tests.rs - unit tests.
Implementation Blueprint
- In src/slashing/types.rs, define EpochIndex = u64 and a new type WindowOffset(u16) with saturating arithmetic.
- Rewrite the accumulator indexing in src/slashing/accumulator.rs to use epoch.wrapping_rem(WINDOW as u64) as u16, but additionally store a window_generation: u16 that increments each time the epoch counter crosses a multiple of WINDOW.
- Modify check_slashed() to compare both the bit in the current window and the generation tag - if the generation matches and the bit is set, the validator is slashed; otherwise it is not.
- On record_slashing(), clear the entire bit for the current validator index and set the new generation.
- Add fuzz tests that drive epoch > 2^16 and verify no false negatives/positives.
Problem Statement / Feature Objective
The slashing condition engine maintains a bitfield accumulator tracking slashing events per validator for MAX_HISTORICAL_EPOCHS = 2^12 epochs. When the current epoch counter wraps past u16::MAX (65535), the accumulator indexing produces an out-of-bounds read or a silent wrap, allowing a previously-slashed validator to escape detection and re-participate.
Technical Invariants & Bounds
Codebase Navigation Guide
Implementation Blueprint