-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,159 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
[package] | ||
name = "module-operations" | ||
version = "0.1.0" | ||
authors.workspace = true | ||
edition.workspace = true | ||
homepage.workspace = true | ||
repository.workspace = true | ||
|
||
[dependencies] | ||
parity-scale-codec = { workspace = true, features = ["derive"] } | ||
scale-info = { workspace = true, features = ["derive"] } | ||
log = { workspace = true } | ||
|
||
frame-support = { workspace = true } | ||
frame-system = { workspace = true } | ||
pallet-session = { workspace = true } | ||
pallet-balances = { workspace = true } | ||
sp-runtime = { workspace = true } | ||
sp-core = { workspace = true } | ||
|
||
[dev-dependencies] | ||
sp-io = { workspace = true } | ||
pallet-staking = { workspace = true } | ||
pallet-timestamp = { workspace = true } | ||
frame-election-provider-support = { workspace = true } | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"parity-scale-codec/std", | ||
"scale-info/std", | ||
"log/std", | ||
|
||
"frame-support/std", | ||
"frame-system/std", | ||
"pallet-session/std", | ||
"pallet-balances/std", | ||
"pallet-staking/std", | ||
"pallet-timestamp/std", | ||
"frame-election-provider-support/std", | ||
"sp-runtime/std", | ||
"sp-core/std", | ||
|
||
] | ||
|
||
try-runtime = [ | ||
"frame-support/try-runtime", | ||
] |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Operations Module | ||
|
||
General ChainOps extrinsic that are used in chain maintenance activities. | ||
|
||
## fix_accounts_consumers_underflow | ||
|
||
An account can have an underflow of a `consumers` counter. | ||
Account categories that are impacted by this issue depends on a chain runtime, | ||
but specifically for AlephNode runtime are as follows: | ||
|
||
* `consumers` == 0, `reserved` > 0 | ||
* `consumers` == 1, `balances.Locks` contain an entry with `id` == `vesting` | ||
* `consumers` == 2, `balances.Locks` contain an entry with `id` == `staking` | ||
* `consumers` == 3, `balances.Locks` contain entries with `id` == `staking` | ||
and account id is in `session.nextKeys` | ||
|
||
`fix_accounts_consumers_underflow` checks if the account falls into one of above | ||
categories, and increase its `consumers` counter. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# To-Do List | ||
|
||
This list contains all TODOs in the Repo | ||
|
||
|
||
<!-- TOC --> | ||
- [To-Do List](#to-do-list) | ||
- [1. Guidelines](#1-guidelines) | ||
- [2. Contribution](#2-contribution) | ||
- [3. Lists](#3-lists) | ||
- [4. Tasks](#4-tasks) | ||
<!-- /TOC --> | ||
|
||
## 1. Guidelines | ||
|
||
Note: Before you write a ToDo in this repo, please read the below guidelines carefully. | ||
|
||
Whenever you write a ToDo, you need to follow this standard syntax | ||
|
||
```rust | ||
//TODO:[file_name:task_number] - task_details | ||
``` | ||
|
||
for example: | ||
|
||
```rust | ||
//TODO:[TODO.md:0] - Add Todo Guidelines | ||
``` | ||
|
||
Note > the `//TODO:[filename:task_number] - ` is what we call the `task_prefix`. | ||
|
||
Whenever adding/writing a Task/ToDo, you need to describe the task on this list. Whenever you write a TODO in any file, add a reference to it here. Please make sure the task reference here is titled correctly and as detailed as possible\. | ||
|
||
Whenever you `complete` a task/TODO from any file, please tick/complete its reference here and make sure you do it in the same `commit` that completes the task. | ||
|
||
Whenever a task is cancelled (discontinued or not needed for w/e reason), please note in the details why it is cancelled, make sure you do it in the same `commit` that removes/cancels the TODO, and add this `-C` as a suffix to its `file_name` in the list here, for example: | ||
|
||
```rust | ||
//TODO:[TODO.md-C:0] - Add Todo Guidelines | ||
``` | ||
|
||
## 2. Contribution | ||
|
||
You can contribute to this list by completing tasks or by adding tasks(TODOs) that are currently in the repo but not on the list. You can also contribute by updating old tasks to the new Standard. | ||
|
||
## 3. Lists | ||
|
||
Each module/crate has its own `TODO.md`. | ||
|
||
## 4. Tasks | ||
|
||
These tasks are just for this file specifically. | ||
|
||
- [x] [[TODO.md:0] - Add TODO.md File](TODO.md): Add a TODO.md file to organise TODOs in the repo. | ||
- [x] [[TODO.md:1] - Add a `task_title`](/TODO.md/#tasks): Adda `task_title`. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// ุจูุณูู ู ุงูููููู ุงูุฑููุญูู ููู ุงูุฑููุญููู | ||
|
||
// This file is part of Setheum. | ||
|
||
// Copyright (C) 2019-Present Setheum Labs. | ||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
//! The Operations Module. | ||
#![allow(clippy::nonminimal_bool)] | ||
|
||
use frame_support::{ | ||
dispatch::DispatchResultWithPostInfo, pallet_prelude::Get, traits::LockIdentifier, | ||
WeakBoundedVec, | ||
}; | ||
use pallet_balances::BalanceLock; | ||
use parity_scale_codec::Encode; | ||
use sp_core::hexdisplay::HexDisplay; | ||
use sp_runtime::DispatchError; | ||
|
||
use crate::{ | ||
pallet::{Config, Event, Pallet}, | ||
traits::{AccountInfoProvider, BalancesProvider, NextKeysSessionProvider}, | ||
LOG_TARGET, STAKING_ID, VESTING_ID, | ||
}; | ||
|
||
impl<T: Config> Pallet<T> { | ||
/// Checks if account has an underflow of `consumers` counter. In such case, it increments | ||
/// it by one. | ||
pub fn fix_underflow_consumer_counter(who: T::AccountId) -> DispatchResultWithPostInfo { | ||
let mut weight = T::DbWeight::get().reads(1); | ||
let consumers = T::AccountInfoProvider::get_consumers(&who); | ||
|
||
weight += T::DbWeight::get().reads(1); | ||
if Self::no_consumers_some_reserved(&who, consumers) { | ||
Self::increment_consumers(who)?; | ||
weight += T::DbWeight::get().writes(1); | ||
return Ok(Some(weight).into()); | ||
} | ||
|
||
weight += T::DbWeight::get().reads(2); | ||
if Self::staker_has_consumers_underflow(&who, consumers) { | ||
Self::increment_consumers(who)?; | ||
weight += T::DbWeight::get().writes(1); | ||
return Ok(Some(weight).into()); | ||
} | ||
|
||
log::debug!( | ||
target: LOG_TARGET, | ||
"Account {:?} has correct consumer counter, not incrementing", | ||
HexDisplay::from(&who.encode()) | ||
); | ||
Ok(Some(weight).into()) | ||
} | ||
|
||
fn staker_has_consumers_underflow(who: &T::AccountId, consumers: u32) -> bool { | ||
let locks = T::BalancesProvider::locks(who); | ||
let has_vesting_lock = Self::has_lock(&locks, VESTING_ID); | ||
let vester_has_consumers_underflow = consumers == 1 && has_vesting_lock; | ||
let has_staking_lock = Self::has_lock(&locks, STAKING_ID); | ||
let nominator_has_consumers_underflow = consumers == 2 && has_staking_lock; | ||
let has_next_session_keys = T::NextKeysSessionProvider::has_next_session_keys(who); | ||
let validator_has_consumers_underflow = | ||
consumers == 3 && has_staking_lock && has_next_session_keys; | ||
vester_has_consumers_underflow | ||
|| nominator_has_consumers_underflow | ||
|| validator_has_consumers_underflow | ||
} | ||
|
||
fn no_consumers_some_reserved(who: &T::AccountId, consumers: u32) -> bool { | ||
let is_reserved_not_zero = T::BalancesProvider::is_reserved_not_zero(who); | ||
|
||
consumers == 0 && is_reserved_not_zero | ||
} | ||
|
||
fn has_lock<U, V>(locks: &WeakBoundedVec<BalanceLock<U>, V>, id: LockIdentifier) -> bool { | ||
locks.iter().any(|x| x.id == id) | ||
} | ||
|
||
fn increment_consumers(who: T::AccountId) -> Result<(), DispatchError> { | ||
frame_system::Pallet::<T>::inc_consumers_without_limit(&who)?; | ||
Self::deposit_event(Event::ConsumersUnderflowFixed { who }); | ||
Ok(()) | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// ุจูุณูู ู ุงูููููู ุงูุฑููุญูู ููู ุงูุฑููุญููู | ||
|
||
// This file is part of Setheum. | ||
|
||
// Copyright (C) 2019-Present Setheum Labs. | ||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
//! The Operations Module. | ||
#![cfg_attr(not(feature = "std"), no_std)] | ||
#![doc = include_str!("../README.md")] | ||
|
||
extern crate core; | ||
|
||
mod impls; | ||
mod traits; | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
|
||
use frame_support::traits::{LockIdentifier, StorageVersion}; | ||
|
||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); | ||
pub const LOG_TARGET: &str = "pallet-operations"; | ||
// harcoding as those consts are not public in substrate | ||
pub const STAKING_ID: LockIdentifier = *b"staking "; | ||
pub const VESTING_ID: LockIdentifier = *b"vesting "; | ||
|
||
pub use pallet::*; | ||
|
||
#[frame_support::pallet] | ||
#[pallet_doc("../README.md")] | ||
pub mod pallet { | ||
use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_REF_TIME_PER_MILLIS}; | ||
use frame_system::{ensure_signed, pallet_prelude::OriginFor}; | ||
|
||
use crate::{ | ||
traits::{AccountInfoProvider, BalancesProvider, NextKeysSessionProvider}, | ||
STORAGE_VERSION, | ||
}; | ||
|
||
#[pallet::config] | ||
pub trait Config: frame_system::Config { | ||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; | ||
/// Something that provides information about an account's consumers counter | ||
type AccountInfoProvider: AccountInfoProvider<AccountId = Self::AccountId, RefCount = u32>; | ||
type BalancesProvider: BalancesProvider<AccountId = Self::AccountId>; | ||
type NextKeysSessionProvider: NextKeysSessionProvider<AccountId = Self::AccountId>; | ||
} | ||
|
||
#[pallet::pallet] | ||
#[pallet::storage_version(STORAGE_VERSION)] | ||
#[pallet::without_storage_info] | ||
pub struct Pallet<T>(_); | ||
|
||
#[pallet::event] | ||
#[pallet::generate_deposit(pub(super) fn deposit_event)] | ||
pub enum Event<T: Config> { | ||
/// An account has fixed its consumers counter underflow | ||
ConsumersUnderflowFixed { who: T::AccountId }, | ||
} | ||
|
||
#[pallet::call] | ||
impl<T: Config> Pallet<T> { | ||
/// An account can have an underflow of a `consumers` counter. | ||
/// Account categories that are impacted by this issue depends on a chain runtime, | ||
/// but specifically for AlephNode runtime are as follows: | ||
/// * `consumers` == 0, `reserved` > 0 | ||
/// * `consumers` == 1, `balances.Locks` contain an entry with `id` == `vesting` | ||
/// * `consumers` == 2, `balances.Locks` contain an entry with `id` == `staking` | ||
/// * `consumers` == 3, `balances.Locks` contain entries with `id` == `staking` | ||
/// and account id is in `session.nextKeys` | ||
/// | ||
/// `fix_accounts_consumers_underflow` checks if the account falls into one of above | ||
/// categories, and increase its `consumers` counter. | ||
/// | ||
/// - `origin`: Must be `Signed`. | ||
/// - `who`: An account to be fixed | ||
/// | ||
#[pallet::call_index(0)] | ||
#[pallet::weight( | ||
Weight::from_parts(WEIGHT_REF_TIME_PER_MILLIS.saturating_mul(8), 0) | ||
)] | ||
pub fn fix_accounts_consumers_underflow( | ||
origin: OriginFor<T>, | ||
who: T::AccountId, | ||
) -> DispatchResultWithPostInfo { | ||
ensure_signed(origin)?; | ||
Self::fix_underflow_consumer_counter(who)?; | ||
Ok(().into()) | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// ุจูุณูู ู ุงูููููู ุงูุฑููุญูู ููู ุงูุฑููุญููู | ||
|
||
// This file is part of Setheum. | ||
|
||
// Copyright (C) 2019-Present Setheum Labs. | ||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
//! Tests for the Operations Module. | ||
mod setup; | ||
mod suite; |
Oops, something went wrong.