Extrinsic to restore corrupt staking ledgers (#3706)

This PR adds a new extrinsic `Call::restore_ledger ` gated by
`StakingAdmin` origin that restores a corrupted staking ledger. This
extrinsic will be used to recover ledgers that were affected by the
issue discussed in
https://github.com/paritytech/polkadot-sdk/issues/3245.

The extrinsic will re-write the storage items associated with a stash
account provided as input parameter. The data used to reset the ledger
can be either i) fetched on-chain or ii) partially/totally set by the
input parameters of the call.

In order to use on-chain data to restore the staking locks, we need a
way to read the current lock in the balances pallet. This PR adds a
`InspectLockableCurrency` trait and implements it in the pallet
balances. An alternative would be to tightly couple staking with the
pallet balances but that's inelegant (an example of how it would look
like in [this
branch](https://github.com/paritytech/polkadot-sdk/tree/gpestana/ledger-badstate-clean_tightly)).

More details on the type of corruptions and corresponding fixes
https://hackmd.io/DLb5jEYWSmmvqXC9ae4yRg?view#/

We verified that the `Call::restore_ledger` does fix all current
corrupted ledgers in Polkadot and Kusama. You can verify it here
https://hackmd.io/v-XNrEoGRpe7APR-EZGhOA.

**Changes introduced**
- Adds `Call::restore_ledger ` extrinsic to recover a corrupted ledger;
- Adds trait `frame_support::traits::currency::InspectLockableCurrency`
to allow external pallets to read current locks given an account and
lock ID;
- Implements the `InspectLockableCurrency` in the pallet-balances.
- Adds staking locks try-runtime checks
(https://github.com/paritytech/polkadot-sdk/issues/3751)

**Todo**
- [x] benchmark `Call::restore_ledger`
- [x] throughout testing of all ledger recovering cases
- [x] consider adding the staking locks try-runtime checks to this PR
(https://github.com/paritytech/polkadot-sdk/issues/3751)
- [x] simulate restoring all ledgers
(https://hackmd.io/Dsa2tvhISNSs7zcqriTaxQ?view) in Polkadot and Kusama
using chopsticks -- https://hackmd.io/v-XNrEoGRpe7APR-EZGhOA

Related to https://github.com/paritytech/polkadot-sdk/issues/3245
Closes https://github.com/paritytech/polkadot-sdk/issues/3751

---------

Co-authored-by: command-bot <>
This commit is contained in:
Gonçalo Pestana
2024-03-27 18:20:24 +01:00
committed by GitHub
parent 374aefa4f2
commit bbdbeb7ec6
15 changed files with 1201 additions and 486 deletions
+2 -2
View File
@@ -22,8 +22,8 @@
pub mod tokens;
pub use tokens::{
currency::{
ActiveIssuanceOf, Currency, LockIdentifier, LockableCurrency, NamedReservableCurrency,
ReservableCurrency, TotalIssuanceOf, VestingSchedule,
ActiveIssuanceOf, Currency, InspectLockableCurrency, LockIdentifier, LockableCurrency,
NamedReservableCurrency, ReservableCurrency, TotalIssuanceOf, VestingSchedule,
},
fungible, fungibles,
imbalance::{Imbalance, OnUnbalanced, SignedImbalance},
@@ -27,7 +27,7 @@ use sp_runtime::{traits::MaybeSerializeDeserialize, DispatchError};
mod reservable;
pub use reservable::{NamedReservableCurrency, ReservableCurrency};
mod lockable;
pub use lockable::{LockIdentifier, LockableCurrency, VestingSchedule};
pub use lockable::{InspectLockableCurrency, LockIdentifier, LockableCurrency, VestingSchedule};
/// Abstraction over a fungible assets system.
pub trait Currency<AccountId> {
@@ -64,6 +64,12 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
fn remove_lock(id: LockIdentifier, who: &AccountId);
}
/// A inspect interface for a currency whose accounts can have liquidity restrictions.
pub trait InspectLockableCurrency<AccountId>: LockableCurrency<AccountId> {
/// Amount of funds locked for `who` associated with `id`.
fn balance_locked(id: LockIdentifier, who: &AccountId) -> Self::Balance;
}
/// A vesting schedule over a currency. This allows a particular currency to have vesting limits
/// applied to it.
pub trait VestingSchedule<AccountId> {