Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AHM] Follow up issues from the staking refactor #7596

Open
13 tasks
Ank4n opened this issue Feb 17, 2025 · 0 comments
Open
13 tasks

[AHM] Follow up issues from the staking refactor #7596

Ank4n opened this issue Feb 17, 2025 · 0 comments
Assignees

Comments

@Ank4n
Copy link
Contributor

Ank4n commented Feb 17, 2025

Creating this to track the followup issues to handle for staking refactors to make it AH ready

Paged Slashing

Link to the original PR.

  • Test HistoricalSession proof works fine with eras before removing exposure as full identity.
  • Properly bench offence processing and slashing.
  • Handle Offences::Reports migration when removing validator exposure as identity.
  • [Low Prio] OCW task to process offence + apply slashes.
  • [Low Prio] Minimum time for governance to cancel deferred slash.
  • [Low Prio] Allow root or staking admin to add a custom slash.

Disabling refactor

Link to the original PR.

  • Maybe merge migration with the older undeployed DisabledValidators migration in pallet-staking.
  • Test that disabled validator resets at era change.
  • Add always sorted try-runtime test for DisabledValidators.
  • More test coverage for the disabling logic in pallet-session.

Others

@Ank4n Ank4n self-assigned this Feb 17, 2025
@Ank4n Ank4n added this to AHM Feb 17, 2025
github-merge-queue bot pushed a commit that referenced this issue Feb 17, 2025
…ication (#7424)

closes #3610.

helps #6344, but need
to migrate storage `Offences::Reports` before we can remove exposure
dependency in RC pallets.

replaces #6788.

## Context  
Slashing in staking is unbounded currently, which is a major blocker
until staking can move to a parachain (AH).

### Current Slashing Process (Unbounded)  

1. **Offence Reported**  
- Offences include multiple validators, each with potentially large
exposure pages.
- Slashes are **computed immediately** and scheduled for application
after **28 eras**.

2. **Slash Applied**  
- All unapplied slashes are executed in **one block** at the start of
the **28th era**. This is an **unbounded operation**.


### Proposed Slashing Process (Bounded)  

1. **Offence Queueing**  
   - Offences are **queued** after basic sanity checks.  

2. **Paged Offence Processing (Computing Slash)**  
   - Slashes are **computed one validator exposure page at a time**.  
   - **Unapplied slashes** are stored in a **double map**:  
     - **Key 1 (k1):** `EraIndex`  
- **Key 2 (k2):** `(Validator, SlashFraction, PageIndex)` — a unique
identifier for each slash page

3. **Paged Slash Application**  
- Slashes are **applied one page at a time** across multiple blocks.
- Slash application starts at the **27th era** (one era earlier than
before) to ensure all slashes are applied **before stakers can unbond**
(which starts from era 28 onwards).

---

## Worst-Case Block Calculation for Slash Application  

### Polkadot:  
- **1 era = 24 hours**, **1 block = 6s** → **14,400 blocks/era**  
- On parachains (**12s blocks**) → **7,200 blocks/era**  

### Kusama:  
- **1 era = 6 hours**, **1 block = 6s** → **3,600 blocks/era**  
- On parachains (**12s blocks**) → **1,800 blocks/era**  

### Worst-Case Assumptions:  
- **Total stakers:** 40,000 nominators, 1000 validators. (Polkadot
currently has ~23k nominators and 500 validators)
- **Max slashed:** 50% so 20k nominators, 250 validators.  
- **Page size:** Validators with multiple page: (512 + 1)/2 = 256 ,
Validators with single page: 1

### Calculation:  
There might be a more accurate way to calculate this worst-case number,
and this estimate could be significantly higher than necessary, but it
shouldn’t exceed this value.

Blocks needed: 250 + 20k/256 = ~330 blocks.

##  *Potential Improvement:*  
- Consider adding an **Offchain Worker (OCW)** task to further optimize
slash application in future updates.
- Dynamically batch unapplied slashes based on number of nominators in
the page, or process until reserved weight limit is exhausted.

----
## Summary of Changes  

### Storage  
- **New:**  
  - `OffenceQueue` *(StorageDoubleMap)*  
    - **K1:** Era  
    - **K2:** Offending validator account  
    - **V:** `OffenceRecord`  
  - `OffenceQueueEras` *(StorageValue)*  
    - **V:** `BoundedVec<EraIndex, BoundingDuration>`  
  - `ProcessingOffence` *(StorageValue)*  
    - **V:** `(Era, offending validator account, OffenceRecord)`  

- **Changed:**  
  - `UnappliedSlashes`:  
    - **Old:** `StorageMap<K -> Era, V -> Vec<UnappliedSlash>>`  
- **New:** `StorageDoubleMap<K1 -> Era, K2 -> (validator_acc, perbill,
page_index), V -> UnappliedSlash>`

### Events  
- **New:**  
  - `SlashComputed { offence_era, slash_era, offender, page }`  
  - `SlashCancelled { slash_era, slash_key, payout }`  

### Error  
- **Changed:**  
  - `InvalidSlashIndex` → Renamed to `InvalidSlashRecord`  
- **Removed:**  
  - `NotSortedAndUnique`  
- **Added:**  
  - `EraNotStarted`  

### Call  
- **Changed:**  
  - `cancel_deferred_slash(era, slash_indices: Vec<u32>)`  
    → Now takes `Vec<(validator_acc, slash_fraction, page_index)>`  
- **New:**  
- `apply_slash(slash_era, slash_key: (validator_acc, slash_fraction,
page_index))`

### Runtime Config  
- `FullIdentification` is now set to a unit type (`()`) / null identity,
replacing the previous exposure type for all runtimes using
`pallet_session::historical`.

## TODO
- [x] Fixed broken `CancelDeferredSlashes`.
- [x] Ensure on_offence called only with validator account for
identification everywhere.
- [ ] Ensure we never need to read full exposure.
- [x] Tests for multi block processing and application of slash.
- [x] Migrate UnappliedSlashes 
- [x] Bench (crude, needs proper bench as followup)
  - [x] on_offence()
  - [x] process_offence()
  - [x] apply_slash()
 
 
## Followups (tracker
[link](#7596))
- [ ] OCW task to process offence + apply slashes.
- [ ] Minimum time for governance to cancel deferred slash.
- [ ] Allow root or staking admin to add a custom slash.
- [ ] Test HistoricalSession proof works fine with eras before removing
exposure as full identity.
- [ ] Properly bench offence processing and slashing.
- [ ] Handle Offences::Reports migration when removing validator
exposure as identity.

---------

Co-authored-by: Gonçalo Pestana <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: Kian Paimani <[email protected]>
Co-authored-by: Guillaume Thiolliere <[email protected]>
Co-authored-by: kianenigma <[email protected]>
Co-authored-by: Giuseppe Re <[email protected]>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
clangenb pushed a commit to clangenb/polkadot-sdk that referenced this issue Feb 19, 2025
…ication (paritytech#7424)

closes paritytech#3610.

helps paritytech#6344, but need
to migrate storage `Offences::Reports` before we can remove exposure
dependency in RC pallets.

replaces paritytech#6788.

## Context  
Slashing in staking is unbounded currently, which is a major blocker
until staking can move to a parachain (AH).

### Current Slashing Process (Unbounded)  

1. **Offence Reported**  
- Offences include multiple validators, each with potentially large
exposure pages.
- Slashes are **computed immediately** and scheduled for application
after **28 eras**.

2. **Slash Applied**  
- All unapplied slashes are executed in **one block** at the start of
the **28th era**. This is an **unbounded operation**.


### Proposed Slashing Process (Bounded)  

1. **Offence Queueing**  
   - Offences are **queued** after basic sanity checks.  

2. **Paged Offence Processing (Computing Slash)**  
   - Slashes are **computed one validator exposure page at a time**.  
   - **Unapplied slashes** are stored in a **double map**:  
     - **Key 1 (k1):** `EraIndex`  
- **Key 2 (k2):** `(Validator, SlashFraction, PageIndex)` — a unique
identifier for each slash page

3. **Paged Slash Application**  
- Slashes are **applied one page at a time** across multiple blocks.
- Slash application starts at the **27th era** (one era earlier than
before) to ensure all slashes are applied **before stakers can unbond**
(which starts from era 28 onwards).

---

## Worst-Case Block Calculation for Slash Application  

### Polkadot:  
- **1 era = 24 hours**, **1 block = 6s** → **14,400 blocks/era**  
- On parachains (**12s blocks**) → **7,200 blocks/era**  

### Kusama:  
- **1 era = 6 hours**, **1 block = 6s** → **3,600 blocks/era**  
- On parachains (**12s blocks**) → **1,800 blocks/era**  

### Worst-Case Assumptions:  
- **Total stakers:** 40,000 nominators, 1000 validators. (Polkadot
currently has ~23k nominators and 500 validators)
- **Max slashed:** 50% so 20k nominators, 250 validators.  
- **Page size:** Validators with multiple page: (512 + 1)/2 = 256 ,
Validators with single page: 1

### Calculation:  
There might be a more accurate way to calculate this worst-case number,
and this estimate could be significantly higher than necessary, but it
shouldn’t exceed this value.

Blocks needed: 250 + 20k/256 = ~330 blocks.

##  *Potential Improvement:*  
- Consider adding an **Offchain Worker (OCW)** task to further optimize
slash application in future updates.
- Dynamically batch unapplied slashes based on number of nominators in
the page, or process until reserved weight limit is exhausted.

----
## Summary of Changes  

### Storage  
- **New:**  
  - `OffenceQueue` *(StorageDoubleMap)*  
    - **K1:** Era  
    - **K2:** Offending validator account  
    - **V:** `OffenceRecord`  
  - `OffenceQueueEras` *(StorageValue)*  
    - **V:** `BoundedVec<EraIndex, BoundingDuration>`  
  - `ProcessingOffence` *(StorageValue)*  
    - **V:** `(Era, offending validator account, OffenceRecord)`  

- **Changed:**  
  - `UnappliedSlashes`:  
    - **Old:** `StorageMap<K -> Era, V -> Vec<UnappliedSlash>>`  
- **New:** `StorageDoubleMap<K1 -> Era, K2 -> (validator_acc, perbill,
page_index), V -> UnappliedSlash>`

### Events  
- **New:**  
  - `SlashComputed { offence_era, slash_era, offender, page }`  
  - `SlashCancelled { slash_era, slash_key, payout }`  

### Error  
- **Changed:**  
  - `InvalidSlashIndex` → Renamed to `InvalidSlashRecord`  
- **Removed:**  
  - `NotSortedAndUnique`  
- **Added:**  
  - `EraNotStarted`  

### Call  
- **Changed:**  
  - `cancel_deferred_slash(era, slash_indices: Vec<u32>)`  
    → Now takes `Vec<(validator_acc, slash_fraction, page_index)>`  
- **New:**  
- `apply_slash(slash_era, slash_key: (validator_acc, slash_fraction,
page_index))`

### Runtime Config  
- `FullIdentification` is now set to a unit type (`()`) / null identity,
replacing the previous exposure type for all runtimes using
`pallet_session::historical`.

## TODO
- [x] Fixed broken `CancelDeferredSlashes`.
- [x] Ensure on_offence called only with validator account for
identification everywhere.
- [ ] Ensure we never need to read full exposure.
- [x] Tests for multi block processing and application of slash.
- [x] Migrate UnappliedSlashes 
- [x] Bench (crude, needs proper bench as followup)
  - [x] on_offence()
  - [x] process_offence()
  - [x] apply_slash()
 
 
## Followups (tracker
[link](paritytech#7596))
- [ ] OCW task to process offence + apply slashes.
- [ ] Minimum time for governance to cancel deferred slash.
- [ ] Allow root or staking admin to add a custom slash.
- [ ] Test HistoricalSession proof works fine with eras before removing
exposure as full identity.
- [ ] Properly bench offence processing and slashing.
- [ ] Handle Offences::Reports migration when removing validator
exposure as identity.

---------

Co-authored-by: Gonçalo Pestana <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: Kian Paimani <[email protected]>
Co-authored-by: Guillaume Thiolliere <[email protected]>
Co-authored-by: kianenigma <[email protected]>
Co-authored-by: Giuseppe Re <[email protected]>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

2 participants
@Ank4n and others