mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 00:17:56 +00:00
Migrate pallet-session to the new pallet macro (#9796)
* Migrate pallet-session to the new pallet macro Signed-off-by: koushiro <koushiro.cqx@gmail.com> * Remove old macros Signed-off-by: koushiro <koushiro.cqx@gmail.com> * Fix Signed-off-by: koushiro <koushiro.cqx@gmail.com>
This commit is contained in:
@@ -19,7 +19,8 @@ use std::vec;
|
||||
|
||||
use beefy_primitives::mmr::MmrLeafVersion;
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types, sp_io::TestExternalities, BasicExternalities,
|
||||
construct_runtime, parameter_types, sp_io::TestExternalities, traits::GenesisBuild,
|
||||
BasicExternalities,
|
||||
};
|
||||
use sp_core::{Hasher, H256};
|
||||
use sp_runtime::{
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
use std::vec;
|
||||
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types, sp_io::TestExternalities, BasicExternalities,
|
||||
construct_runtime, parameter_types, sp_io::TestExternalities, traits::GenesisBuild,
|
||||
BasicExternalities,
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
|
||||
@@ -13,38 +13,40 @@ readme = "README.md"
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
|
||||
"derive",
|
||||
] }
|
||||
log = { version = "0.4.0", default-features = false }
|
||||
impl-trait-for-tuples = "0.2.1"
|
||||
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
|
||||
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
|
||||
|
||||
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
|
||||
sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
|
||||
sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
|
||||
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
|
||||
sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" }
|
||||
sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" }
|
||||
sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../primitives/trie", optional = true }
|
||||
|
||||
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
|
||||
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
|
||||
pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" }
|
||||
sp-trie = { version = "4.0.0-dev", optional = true, default-features = false, path = "../../primitives/trie" }
|
||||
log = { version = "0.4.0", default-features = false }
|
||||
impl-trait-for-tuples = "0.2.1"
|
||||
|
||||
[features]
|
||||
default = ["std", "historical"]
|
||||
historical = ["sp-trie"]
|
||||
std = [
|
||||
"log/std",
|
||||
"codec/std",
|
||||
"scale-info/std",
|
||||
"sp-std/std",
|
||||
"sp-io/std",
|
||||
"frame-support/std",
|
||||
"sp-core/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"sp-session/std",
|
||||
"sp-staking/std",
|
||||
"pallet-timestamp/std",
|
||||
"sp-trie/std",
|
||||
"log/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"pallet-timestamp/std",
|
||||
]
|
||||
try-runtime = ["frame-support/try-runtime"]
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Session Module
|
||||
# Session Pallet
|
||||
|
||||
The Session module allows validators to manage their session keys, provides a function for changing
|
||||
the session length, and handles session rotation.
|
||||
|
||||
- [`session::Trait`](https://docs.rs/pallet-session/latest/pallet_session/trait.Config.html)
|
||||
- [`Call`](https://docs.rs/pallet-session/latest/pallet_session/enum.Call.html)
|
||||
- [`Module`](https://docs.rs/pallet-session/latest/pallet_session/struct.Module.html)
|
||||
- [`Pallet`](https://docs.rs/pallet-session/latest/pallet_session/struct.Pallet.html)
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -72,11 +72,11 @@ The [Staking pallet](https://docs.rs/pallet-staking/latest/pallet_staking/) uses
|
||||
use pallet_session as session;
|
||||
|
||||
fn validators<T: pallet_session::Config>() -> Vec<<T as pallet_session::Config>::ValidatorId> {
|
||||
<pallet_session::Module<T>>::validators()
|
||||
<pallet_session::Pallet<T>>::validators()
|
||||
}
|
||||
```
|
||||
|
||||
## Related Modules
|
||||
## Related Pallets
|
||||
|
||||
- [Staking](https://docs.rs/pallet-staking/latest/pallet_staking/)
|
||||
|
||||
|
||||
@@ -13,39 +13,37 @@ readme = "README.md"
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" }
|
||||
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
|
||||
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
|
||||
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
|
||||
frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" }
|
||||
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
|
||||
pallet-staking = { version = "4.0.0-dev", default-features = false, features = [
|
||||
"runtime-benchmarks",
|
||||
], path = "../../staking" }
|
||||
pallet-session = { version = "4.0.0-dev", default-features = false, path = "../../session" }
|
||||
rand = { version = "0.7.2", default-features = false }
|
||||
|
||||
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
|
||||
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
|
||||
sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" }
|
||||
|
||||
frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" }
|
||||
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
|
||||
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
|
||||
pallet-session = { version = "4.0.0-dev", default-features = false, path = "../../session" }
|
||||
pallet-staking = { version = "4.0.0-dev", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" }
|
||||
|
||||
[dev-dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", features = [
|
||||
"derive",
|
||||
] }
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] }
|
||||
scale-info = "1.0"
|
||||
sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
|
||||
pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" }
|
||||
sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }
|
||||
pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" }
|
||||
pallet-balances = { version = "4.0.0-dev", path = "../../balances" }
|
||||
pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" }
|
||||
pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" }
|
||||
frame-election-provider-support = { version = "4.0.0-dev", path = "../../election-provider-support" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"sp-std/std",
|
||||
"sp-session/std",
|
||||
"sp-runtime/std",
|
||||
"frame-system/std",
|
||||
"sp-session/std",
|
||||
"frame-benchmarking/std",
|
||||
"frame-support/std",
|
||||
"pallet-staking/std",
|
||||
"frame-system/std",
|
||||
"pallet-session/std",
|
||||
"pallet-staking/std",
|
||||
]
|
||||
|
||||
@@ -30,7 +30,7 @@ use frame_support::{
|
||||
traits::{KeyOwnerProofSystem, OnInitialize},
|
||||
};
|
||||
use frame_system::RawOrigin;
|
||||
use pallet_session::{historical::Module as Historical, Module as Session, *};
|
||||
use pallet_session::{historical::Module as Historical, Pallet as Session, *};
|
||||
use pallet_staking::{
|
||||
benchmarking::create_validator_with_nominators, testing_utils::create_validators,
|
||||
RewardDestination,
|
||||
@@ -39,7 +39,7 @@ use sp_runtime::traits::{One, StaticLookup};
|
||||
|
||||
const MAX_VALIDATORS: u32 = 1000;
|
||||
|
||||
pub struct Pallet<T: Config>(pallet_session::Module<T>);
|
||||
pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
|
||||
pub trait Config:
|
||||
pallet_session::Config + pallet_session::historical::Config + pallet_staking::Config
|
||||
{
|
||||
@@ -47,7 +47,7 @@ pub trait Config:
|
||||
|
||||
impl<T: Config> OnInitialize<T::BlockNumber> for Pallet<T> {
|
||||
fn on_initialize(n: T::BlockNumber) -> frame_support::weights::Weight {
|
||||
pallet_session::Module::<T>::on_initialize(n)
|
||||
pallet_session::Pallet::<T>::on_initialize(n)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
//! These roots and proofs of inclusion can be generated at any time during the current session.
|
||||
//! Afterwards, the proofs can be fed to a consensus module when reporting misbehavior.
|
||||
|
||||
use super::{Module as SessionModule, SessionIndex};
|
||||
use super::{Pallet as SessionModule, SessionIndex};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{
|
||||
decl_module, decl_storage, print,
|
||||
@@ -114,11 +114,11 @@ impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
|
||||
type ValidatorIdOf = T::ValidatorIdOf;
|
||||
|
||||
fn session_index() -> sp_staking::SessionIndex {
|
||||
super::Module::<T>::current_index()
|
||||
super::Pallet::<T>::current_index()
|
||||
}
|
||||
|
||||
fn validators() -> Vec<Self::ValidatorId> {
|
||||
super::Module::<T>::validators()
|
||||
super::Pallet::<T>::validators()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,11 +366,13 @@ pub(crate) mod tests {
|
||||
use crate::mock::{
|
||||
force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS,
|
||||
};
|
||||
|
||||
use sp_runtime::{key_types::DUMMY, testing::UintAuthorityId};
|
||||
|
||||
use frame_support::{
|
||||
traits::{KeyOwnerProofSystem, OnInitialize},
|
||||
traits::{GenesisBuild, KeyOwnerProofSystem, OnInitialize},
|
||||
BasicExternalities,
|
||||
};
|
||||
use sp_runtime::{key_types::DUMMY, testing::UintAuthorityId};
|
||||
|
||||
type Historical = Module<Test>;
|
||||
|
||||
|
||||
@@ -30,15 +30,11 @@ use sp_runtime::{
|
||||
KeyTypeId,
|
||||
};
|
||||
use sp_session::MembershipProof;
|
||||
|
||||
use super::{
|
||||
super::{Pallet as SessionModule, SessionIndex},
|
||||
Config, IdentificationTuple, ProvingTrie,
|
||||
};
|
||||
|
||||
use super::shared;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
use super::{shared, Config, IdentificationTuple, ProvingTrie};
|
||||
use crate::{Pallet as SessionModule, SessionIndex};
|
||||
|
||||
/// A set of validators, which was used for a fixed session index.
|
||||
struct ValidatorSet<T: Config> {
|
||||
validator_set: Vec<IdentificationTuple<T>>,
|
||||
@@ -142,23 +138,24 @@ pub fn keep_newest<T: Config>(n_to_keep: usize) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{onchain, Module},
|
||||
*,
|
||||
};
|
||||
use crate::mock::{
|
||||
force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS,
|
||||
use super::*;
|
||||
use crate::{
|
||||
historical::{onchain, Module},
|
||||
mock::{force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS},
|
||||
};
|
||||
|
||||
use codec::Encode;
|
||||
use frame_support::traits::{KeyOwnerProofSystem, OnInitialize};
|
||||
use sp_core::{
|
||||
crypto::key_types::DUMMY,
|
||||
offchain::{testing::TestOffchainExt, OffchainDbExt, OffchainWorkerExt, StorageKind},
|
||||
};
|
||||
|
||||
use frame_support::BasicExternalities;
|
||||
use sp_runtime::testing::UintAuthorityId;
|
||||
|
||||
use frame_support::{
|
||||
traits::{GenesisBuild, KeyOwnerProofSystem, OnInitialize},
|
||||
BasicExternalities,
|
||||
};
|
||||
|
||||
type Historical = Module<Test>;
|
||||
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
|
||||
@@ -19,15 +19,11 @@
|
||||
|
||||
use codec::Encode;
|
||||
use sp_runtime::traits::Convert;
|
||||
|
||||
use super::{
|
||||
super::{Config as SessionConfig, Pallet as SessionModule, SessionIndex},
|
||||
Config as HistoricalConfig,
|
||||
};
|
||||
|
||||
use super::shared;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
use super::{shared, Config as HistoricalConfig};
|
||||
use crate::{Config as SessionConfig, Pallet as SessionModule, SessionIndex};
|
||||
|
||||
/// Store the validator-set associated to the `session_index` to the off-chain database.
|
||||
///
|
||||
/// Further processing is then done [`off-chain side`](super::offchain).
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//! Shared logic between on-chain and off-chain components used for slashing using an off-chain
|
||||
//! worker.
|
||||
|
||||
use super::SessionIndex;
|
||||
use codec::Encode;
|
||||
use sp_staking::SessionIndex;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
pub(super) const PREFIX: &[u8] = b"session_historical";
|
||||
|
||||
+238
-191
@@ -15,14 +15,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! # Session Module
|
||||
//! # Session Pallet
|
||||
//!
|
||||
//! The Session module allows validators to manage their session keys, provides a function for
|
||||
//! The Session pallet allows validators to manage their session keys, provides a function for
|
||||
//! changing the session length, and handles session rotation.
|
||||
//!
|
||||
//! - [`Config`]
|
||||
//! - [`Call`]
|
||||
//! - [`Module`]
|
||||
//! - [`Pallet`]
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
@@ -95,12 +95,12 @@
|
||||
//! use pallet_session as session;
|
||||
//!
|
||||
//! fn validators<T: pallet_session::Config>() -> Vec<<T as pallet_session::Config>::ValidatorId> {
|
||||
//! <pallet_session::Module<T>>::validators()
|
||||
//! <pallet_session::Pallet<T>>::validators()
|
||||
//! }
|
||||
//! # fn main(){}
|
||||
//! ```
|
||||
//!
|
||||
//! ## Related Modules
|
||||
//! ## Related Pallets
|
||||
//!
|
||||
//! - [Staking](../pallet_staking/index.html)
|
||||
|
||||
@@ -114,22 +114,9 @@ mod mock;
|
||||
mod tests;
|
||||
pub mod weights;
|
||||
|
||||
use codec::{Decode, MaxEncodedLen};
|
||||
use frame_support::{
|
||||
decl_error, decl_event, decl_module, decl_storage,
|
||||
dispatch::{self, DispatchError, DispatchResult},
|
||||
ensure,
|
||||
traits::{
|
||||
EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get, OneSessionHandler,
|
||||
ValidatorRegistration, ValidatorSet,
|
||||
},
|
||||
weights::Weight,
|
||||
ConsensusEngineId, Parameter,
|
||||
};
|
||||
use frame_system::ensure_signed;
|
||||
use sp_runtime::{
|
||||
traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero},
|
||||
KeyTypeId, Perbill, Permill, RuntimeAppPublic,
|
||||
ConsensusEngineId, KeyTypeId, Perbill, Permill, RuntimeAppPublic,
|
||||
};
|
||||
use sp_staking::SessionIndex;
|
||||
use sp_std::{
|
||||
@@ -137,6 +124,20 @@ use sp_std::{
|
||||
ops::{Rem, Sub},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use frame_support::{
|
||||
codec::{Decode, MaxEncodedLen},
|
||||
dispatch::{DispatchError, DispatchResult},
|
||||
ensure,
|
||||
traits::{
|
||||
EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get, OneSessionHandler,
|
||||
StorageVersion, ValidatorRegistration, ValidatorSet,
|
||||
},
|
||||
weights::Weight,
|
||||
Parameter,
|
||||
};
|
||||
|
||||
pub use pallet::*;
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
/// Decides whether the session should be ended.
|
||||
@@ -228,7 +229,7 @@ pub trait SessionManager<ValidatorId> {
|
||||
///
|
||||
/// Even if the validator-set is the same as before, if any underlying economic conditions have
|
||||
/// changed (i.e. stake-weights), the new validator set must be returned. This is necessary for
|
||||
/// consensus engines making use of the session module to issue a validator-set change so
|
||||
/// consensus engines making use of the session pallet to issue a validator-set change so
|
||||
/// misbehavior can be provably associated with the new economic conditions as opposed to the
|
||||
/// old. The returned validator set, if any, will not be applied until `new_index`. `new_index`
|
||||
/// is strictly greater than from previous call.
|
||||
@@ -280,7 +281,7 @@ pub trait SessionHandler<ValidatorId> {
|
||||
fn on_genesis_session<Ks: OpaqueKeys>(validators: &[(ValidatorId, Ks)]);
|
||||
|
||||
/// Session set has changed; act appropriately. Note that this can be called
|
||||
/// before initialization of your module.
|
||||
/// before initialization of your pallet.
|
||||
///
|
||||
/// `changed` is true whenever any of the session keys or underlying economic
|
||||
/// identities or weightings behind those keys has changed.
|
||||
@@ -356,86 +357,83 @@ impl<AId> SessionHandler<AId> for TestSessionHandler {
|
||||
fn on_disabled(_: usize) {}
|
||||
}
|
||||
|
||||
impl<T: Config> ValidatorRegistration<T::ValidatorId> for Module<T> {
|
||||
fn is_registered(id: &T::ValidatorId) -> bool {
|
||||
Self::load_keys(id).is_some()
|
||||
}
|
||||
}
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
pub trait Config: frame_system::Config {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event> + Into<<Self as frame_system::Config>::Event>;
|
||||
/// The current storage version.
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
|
||||
|
||||
/// A stable ID for a validator.
|
||||
type ValidatorId: Member + Parameter + MaxEncodedLen;
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(super) trait Store)]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
/// A conversion from account ID to validator ID.
|
||||
///
|
||||
/// Its cost must be at most one storage read.
|
||||
type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event> + IsType<<Self as frame_system::Config>::Event>;
|
||||
|
||||
/// Indicator for when to end the session.
|
||||
type ShouldEndSession: ShouldEndSession<Self::BlockNumber>;
|
||||
/// A stable ID for a validator.
|
||||
type ValidatorId: Member + Parameter + MaybeSerializeDeserialize + MaxEncodedLen;
|
||||
|
||||
/// Something that can predict the next session rotation. This should typically come from the
|
||||
/// same logical unit that provides [`ShouldEndSession`], yet, it gives a best effort estimate.
|
||||
/// It is helpful to implement [`EstimateNextNewSession`].
|
||||
type NextSessionRotation: EstimateNextSessionRotation<Self::BlockNumber>;
|
||||
|
||||
/// Handler for managing new session.
|
||||
type SessionManager: SessionManager<Self::ValidatorId>;
|
||||
|
||||
/// Handler when a session has changed.
|
||||
type SessionHandler: SessionHandler<Self::ValidatorId>;
|
||||
|
||||
/// The keys.
|
||||
type Keys: OpaqueKeys + Member + Parameter + Default;
|
||||
|
||||
/// The fraction of validators set that is safe to be disabled.
|
||||
///
|
||||
/// After the threshold is reached `disabled` method starts to return true,
|
||||
/// which in combination with `pallet_staking` forces a new era.
|
||||
type DisabledValidatorsThreshold: Get<Perbill>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Config> as Session {
|
||||
/// The current set of validators.
|
||||
Validators get(fn validators): Vec<T::ValidatorId>;
|
||||
|
||||
/// Current index of the session.
|
||||
CurrentIndex get(fn current_index): SessionIndex;
|
||||
|
||||
/// True if the underlying economic identities or weighting behind the validators
|
||||
/// has changed in the queued validator set.
|
||||
QueuedChanged: bool;
|
||||
|
||||
/// The queued keys for the next session. When the next session begins, these keys
|
||||
/// will be used to determine the validator's session keys.
|
||||
QueuedKeys get(fn queued_keys): Vec<(T::ValidatorId, T::Keys)>;
|
||||
|
||||
/// Indices of disabled validators.
|
||||
/// A conversion from account ID to validator ID.
|
||||
///
|
||||
/// The set is cleared when `on_session_ending` returns a new set of identities.
|
||||
DisabledValidators get(fn disabled_validators): Vec<u32>;
|
||||
/// Its cost must be at most one storage read.
|
||||
type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
|
||||
|
||||
/// The next session keys for a validator.
|
||||
NextKeys: map hasher(twox_64_concat) T::ValidatorId => Option<T::Keys>;
|
||||
/// Indicator for when to end the session.
|
||||
type ShouldEndSession: ShouldEndSession<Self::BlockNumber>;
|
||||
|
||||
/// The owner of a key. The key is the `KeyTypeId` + the encoded key.
|
||||
KeyOwner: map hasher(twox_64_concat) (KeyTypeId, Vec<u8>) => Option<T::ValidatorId>;
|
||||
/// Something that can predict the next session rotation. This should typically come from
|
||||
/// the same logical unit that provides [`ShouldEndSession`], yet, it gives a best effort
|
||||
/// estimate. It is helpful to implement [`EstimateNextNewSession`].
|
||||
type NextSessionRotation: EstimateNextSessionRotation<Self::BlockNumber>;
|
||||
|
||||
/// Handler for managing new session.
|
||||
type SessionManager: SessionManager<Self::ValidatorId>;
|
||||
|
||||
/// Handler when a session has changed.
|
||||
type SessionHandler: SessionHandler<Self::ValidatorId>;
|
||||
|
||||
/// The keys.
|
||||
type Keys: OpaqueKeys + Member + Parameter + Default + MaybeSerializeDeserialize;
|
||||
|
||||
/// The fraction of validators set that is safe to be disabled.
|
||||
///
|
||||
/// After the threshold is reached `disabled` method starts to return true,
|
||||
/// which in combination with `pallet_staking` forces a new era.
|
||||
type DisabledValidatorsThreshold: Get<Perbill>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(keys): Vec<(T::AccountId, T::ValidatorId, T::Keys)>;
|
||||
build(|config: &GenesisConfig<T>| {
|
||||
|
||||
#[pallet::genesis_config]
|
||||
pub struct GenesisConfig<T: Config> {
|
||||
pub keys: Vec<(T::AccountId, T::ValidatorId, T::Keys)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: Config> Default for GenesisConfig<T> {
|
||||
fn default() -> Self {
|
||||
Self { keys: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
|
||||
fn build(&self) {
|
||||
if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() {
|
||||
panic!("Number of keys in session handler and session keys does not match");
|
||||
}
|
||||
|
||||
T::SessionHandler::KEY_TYPE_IDS.iter().zip(T::Keys::key_ids()).enumerate()
|
||||
T::SessionHandler::KEY_TYPE_IDS
|
||||
.iter()
|
||||
.zip(T::Keys::key_ids())
|
||||
.enumerate()
|
||||
.for_each(|(i, (sk, kk))| {
|
||||
if sk != kk {
|
||||
panic!(
|
||||
@@ -445,8 +443,8 @@ decl_storage! {
|
||||
}
|
||||
});
|
||||
|
||||
for (account, val, keys) in config.keys.iter().cloned() {
|
||||
<Module<T>>::inner_set_keys(&val, keys)
|
||||
for (account, val, keys) in self.keys.iter().cloned() {
|
||||
<Pallet<T>>::inner_set_keys(&val, keys)
|
||||
.expect("genesis config must not contain duplicates; qed");
|
||||
if frame_system::Pallet::<T>::inc_consumers(&account).is_err() {
|
||||
// This will leak a provider reference, however it only happens once (at
|
||||
@@ -457,25 +455,30 @@ decl_storage! {
|
||||
}
|
||||
}
|
||||
|
||||
let initial_validators_0 = T::SessionManager::new_session_genesis(0)
|
||||
.unwrap_or_else(|| {
|
||||
frame_support::print("No initial validator provided by `SessionManager`, use \
|
||||
session config keys to generate initial validator set.");
|
||||
config.keys.iter().map(|x| x.1.clone()).collect()
|
||||
let initial_validators_0 =
|
||||
T::SessionManager::new_session_genesis(0).unwrap_or_else(|| {
|
||||
frame_support::print(
|
||||
"No initial validator provided by `SessionManager`, use \
|
||||
session config keys to generate initial validator set.",
|
||||
);
|
||||
self.keys.iter().map(|x| x.1.clone()).collect()
|
||||
});
|
||||
assert!(!initial_validators_0.is_empty(), "Empty validator set for session 0 in genesis block!");
|
||||
assert!(
|
||||
!initial_validators_0.is_empty(),
|
||||
"Empty validator set for session 0 in genesis block!"
|
||||
);
|
||||
|
||||
let initial_validators_1 = T::SessionManager::new_session_genesis(1)
|
||||
.unwrap_or_else(|| initial_validators_0.clone());
|
||||
assert!(!initial_validators_1.is_empty(), "Empty validator set for session 1 in genesis block!");
|
||||
assert!(
|
||||
!initial_validators_1.is_empty(),
|
||||
"Empty validator set for session 1 in genesis block!"
|
||||
);
|
||||
|
||||
let queued_keys: Vec<_> = initial_validators_1
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|v| (
|
||||
v.clone(),
|
||||
<Module<T>>::load_keys(&v).unwrap_or_default(),
|
||||
))
|
||||
.map(|v| (v.clone(), <Pallet<T>>::load_keys(&v).unwrap_or_default()))
|
||||
.collect();
|
||||
|
||||
// Tell everyone about the genesis session keys
|
||||
@@ -485,21 +488,62 @@ decl_storage! {
|
||||
<QueuedKeys<T>>::put(queued_keys);
|
||||
|
||||
T::SessionManager::start_session(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl_event!(
|
||||
/// The current set of validators.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn validators)]
|
||||
pub type Validators<T: Config> = StorageValue<_, Vec<T::ValidatorId>, ValueQuery>;
|
||||
|
||||
/// Current index of the session.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn current_index)]
|
||||
pub type CurrentIndex<T> = StorageValue<_, SessionIndex, ValueQuery>;
|
||||
|
||||
/// True if the underlying economic identities or weighting behind the validators
|
||||
/// has changed in the queued validator set.
|
||||
#[pallet::storage]
|
||||
pub type QueuedChanged<T> = StorageValue<_, bool, ValueQuery>;
|
||||
|
||||
/// The queued keys for the next session. When the next session begins, these keys
|
||||
/// will be used to determine the validator's session keys.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn queued_keys)]
|
||||
pub type QueuedKeys<T: Config> = StorageValue<_, Vec<(T::ValidatorId, T::Keys)>, ValueQuery>;
|
||||
|
||||
/// Indices of disabled validators.
|
||||
///
|
||||
/// The set is cleared when `on_session_ending` returns a new set of identities.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn disabled_validators)]
|
||||
pub type DisabledValidators<T> = StorageValue<_, Vec<u32>, ValueQuery>;
|
||||
|
||||
/// The next session keys for a validator.
|
||||
#[pallet::storage]
|
||||
pub type NextKeys<T: Config> =
|
||||
StorageMap<_, Twox64Concat, T::ValidatorId, T::Keys, OptionQuery>;
|
||||
|
||||
/// The owner of a key. The key is the `KeyTypeId` + the encoded key.
|
||||
#[pallet::storage]
|
||||
pub type KeyOwner<T: Config> =
|
||||
StorageMap<_, Twox64Concat, (KeyTypeId, Vec<u8>), T::ValidatorId, OptionQuery>;
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event {
|
||||
/// New session has happened. Note that the argument is the \[session_index\], not the
|
||||
/// block number as the type might suggest.
|
||||
NewSession(SessionIndex),
|
||||
}
|
||||
);
|
||||
|
||||
decl_error! {
|
||||
/// Error for the session module.
|
||||
pub enum Error for Module<T: Config> {
|
||||
/// Old name generated by `decl_event`.
|
||||
#[deprecated(note = "use `Event` instead")]
|
||||
pub type RawEvent = Event;
|
||||
|
||||
/// Error for the session pallet.
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// Invalid ownership proof.
|
||||
InvalidProof,
|
||||
/// No associated validator ID for account.
|
||||
@@ -511,57 +555,9 @@ decl_error! {
|
||||
/// Key setting account is not live, so it's impossible to associate keys.
|
||||
NoAccount,
|
||||
}
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Config> for enum Call where origin: T::Origin {
|
||||
type Error = Error<T>;
|
||||
|
||||
fn deposit_event() = default;
|
||||
|
||||
/// Sets the session key(s) of the function caller to `keys`.
|
||||
/// Allows an account to set its session key prior to becoming a validator.
|
||||
/// This doesn't take effect until the next session.
|
||||
///
|
||||
/// The dispatch origin of this function must be signed.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Complexity: `O(1)`
|
||||
/// Actual cost depends on the number of length of `T::Keys::key_ids()` which is fixed.
|
||||
/// - DbReads: `origin account`, `T::ValidatorIdOf`, `NextKeys`
|
||||
/// - DbWrites: `origin account`, `NextKeys`
|
||||
/// - DbReads per key id: `KeyOwner`
|
||||
/// - DbWrites per key id: `KeyOwner`
|
||||
/// # </weight>
|
||||
#[weight = T::WeightInfo::set_keys()]
|
||||
pub fn set_keys(origin, keys: T::Keys, proof: Vec<u8>) -> dispatch::DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
|
||||
ensure!(keys.ownership_proof_is_valid(&proof), Error::<T>::InvalidProof);
|
||||
|
||||
Self::do_set_keys(&who, keys)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes any session key(s) of the function caller.
|
||||
/// This doesn't take effect until the next session.
|
||||
///
|
||||
/// The dispatch origin of this function must be signed.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Complexity: `O(1)` in number of key types.
|
||||
/// Actual cost depends on the number of length of `T::Keys::key_ids()` which is fixed.
|
||||
/// - DbReads: `T::ValidatorIdOf`, `NextKeys`, `origin account`
|
||||
/// - DbWrites: `NextKeys`, `origin account`
|
||||
/// - DbWrites per key id: `KeyOwner`
|
||||
/// # </weight>
|
||||
#[weight = T::WeightInfo::purge_keys()]
|
||||
pub fn purge_keys(origin) {
|
||||
let who = ensure_signed(origin)?;
|
||||
Self::do_purge_keys(&who)?;
|
||||
}
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
/// Called when a block is initialized. Will rotate session if it is the last
|
||||
/// block of the current session.
|
||||
fn on_initialize(n: T::BlockNumber) -> Weight {
|
||||
@@ -576,17 +572,62 @@ decl_module! {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Sets the session key(s) of the function caller to `keys`.
|
||||
/// Allows an account to set its session key prior to becoming a validator.
|
||||
/// This doesn't take effect until the next session.
|
||||
///
|
||||
/// The dispatch origin of this function must be signed.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Complexity: `O(1)`. Actual cost depends on the number of length of
|
||||
/// `T::Keys::key_ids()` which is fixed.
|
||||
/// - DbReads: `origin account`, `T::ValidatorIdOf`, `NextKeys`
|
||||
/// - DbWrites: `origin account`, `NextKeys`
|
||||
/// - DbReads per key id: `KeyOwner`
|
||||
/// - DbWrites per key id: `KeyOwner`
|
||||
/// # </weight>
|
||||
#[pallet::weight(T::WeightInfo::set_keys())]
|
||||
pub fn set_keys(origin: OriginFor<T>, keys: T::Keys, proof: Vec<u8>) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
ensure!(keys.ownership_proof_is_valid(&proof), Error::<T>::InvalidProof);
|
||||
|
||||
Self::do_set_keys(&who, keys)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes any session key(s) of the function caller.
|
||||
/// This doesn't take effect until the next session.
|
||||
///
|
||||
/// The dispatch origin of this function must be signed.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Complexity: `O(1)` in number of key types. Actual cost depends on the number of length
|
||||
/// of `T::Keys::key_ids()` which is fixed.
|
||||
/// - DbReads: `T::ValidatorIdOf`, `NextKeys`, `origin account`
|
||||
/// - DbWrites: `NextKeys`, `origin account`
|
||||
/// - DbWrites per key id: `KeyOwner`
|
||||
/// # </weight>
|
||||
#[pallet::weight(T::WeightInfo::purge_keys())]
|
||||
pub fn purge_keys(origin: OriginFor<T>) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
Self::do_purge_keys(&who)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Module<T> {
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Move on to next session. Register new validator set and session keys. Changes to the
|
||||
/// validator set have a session of delay to take effect. This allows for equivocation
|
||||
/// punishment after a fork.
|
||||
pub fn rotate_session() {
|
||||
let session_index = CurrentIndex::get();
|
||||
let session_index = <CurrentIndex<T>>::get();
|
||||
log::trace!(target: "runtime::session", "rotating session {:?}", session_index);
|
||||
|
||||
let changed = QueuedChanged::get();
|
||||
let changed = <QueuedChanged<T>>::get();
|
||||
|
||||
// Inform the session handlers that a session is going to end.
|
||||
T::SessionHandler::on_before_session_ending();
|
||||
@@ -600,12 +641,12 @@ impl<T: Config> Module<T> {
|
||||
|
||||
if changed {
|
||||
// reset disabled validators
|
||||
DisabledValidators::take();
|
||||
<DisabledValidators<T>>::take();
|
||||
}
|
||||
|
||||
// Increment session index.
|
||||
let session_index = session_index + 1;
|
||||
CurrentIndex::put(session_index);
|
||||
<CurrentIndex<T>>::put(session_index);
|
||||
|
||||
T::SessionManager::start_session(session_index);
|
||||
|
||||
@@ -655,7 +696,7 @@ impl<T: Config> Module<T> {
|
||||
};
|
||||
|
||||
<QueuedKeys<T>>::put(queued_amalgamated.clone());
|
||||
QueuedChanged::put(next_changed);
|
||||
<QueuedChanged<T>>::put(next_changed);
|
||||
|
||||
// Record that this happened.
|
||||
Self::deposit_event(Event::NewSession(session_index));
|
||||
@@ -669,7 +710,7 @@ impl<T: Config> Module<T> {
|
||||
/// Returns `true` if this causes a `DisabledValidatorsThreshold` of validators
|
||||
/// to be already disabled.
|
||||
pub fn disable_index(i: usize) -> bool {
|
||||
let (fire_event, threshold_reached) = DisabledValidators::mutate(|disabled| {
|
||||
let (fire_event, threshold_reached) = <DisabledValidators<T>>::mutate(|disabled| {
|
||||
let i = i as u32;
|
||||
if let Err(index) = disabled.binary_search(&i) {
|
||||
let count = <Validators<T>>::decode_len().unwrap_or(0) as u32;
|
||||
@@ -688,12 +729,12 @@ impl<T: Config> Module<T> {
|
||||
threshold_reached
|
||||
}
|
||||
|
||||
/// Disable the validator identified by `c`. (If using with the staking module,
|
||||
/// Disable the validator identified by `c`. (If using with the staking pallet,
|
||||
/// this would be their *stash* account.)
|
||||
///
|
||||
/// Returns `Ok(true)` if more than `DisabledValidatorsThreshold` validators in current
|
||||
/// session is already disabled.
|
||||
/// If used with the staking module it allows to force a new era in such case.
|
||||
/// If used with the staking pallet it allows to force a new era in such case.
|
||||
pub fn disable(c: &T::ValidatorId) -> sp_std::result::Result<bool, ()> {
|
||||
Self::validators()
|
||||
.iter()
|
||||
@@ -711,7 +752,7 @@ impl<T: Config> Module<T> {
|
||||
///
|
||||
/// Care should be taken that the raw versions of the
|
||||
/// added keys are unique for every `ValidatorId, KeyTypeId` combination.
|
||||
/// This is an invariant that the session module typically maintains internally.
|
||||
/// This is an invariant that the session pallet typically maintains internally.
|
||||
///
|
||||
/// As the actual values of the keys are typically not known at runtime upgrade,
|
||||
/// it's recommended to initialize the keys to a (unique) dummy value with the expectation
|
||||
@@ -756,7 +797,7 @@ impl<T: Config> Module<T> {
|
||||
///
|
||||
/// This ensures that the reference counter in system is incremented appropriately and as such
|
||||
/// must accept an account ID, rather than a validator ID.
|
||||
fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> dispatch::DispatchResult {
|
||||
fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> DispatchResult {
|
||||
let who = T::ValidatorIdOf::convert(account.clone())
|
||||
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
|
||||
|
||||
@@ -850,16 +891,40 @@ impl<T: Config> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
|
||||
impl<T: Config> ValidatorRegistration<T::ValidatorId> for Pallet<T> {
|
||||
fn is_registered(id: &T::ValidatorId) -> bool {
|
||||
Self::load_keys(id).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
|
||||
type ValidatorId = T::ValidatorId;
|
||||
type ValidatorIdOf = T::ValidatorIdOf;
|
||||
|
||||
fn session_index() -> sp_staking::SessionIndex {
|
||||
Module::<T>::current_index()
|
||||
Pallet::<T>::current_index()
|
||||
}
|
||||
|
||||
fn validators() -> Vec<Self::ValidatorId> {
|
||||
Module::<T>::validators()
|
||||
Pallet::<T>::validators()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> EstimateNextNewSession<T::BlockNumber> for Pallet<T> {
|
||||
fn average_session_length() -> T::BlockNumber {
|
||||
T::NextSessionRotation::average_session_length()
|
||||
}
|
||||
|
||||
/// This session pallet always calls new_session and next_session at the same time, hence we
|
||||
/// do a simple proxy and pass the function to next rotation.
|
||||
fn estimate_next_new_session(now: T::BlockNumber) -> (Option<T::BlockNumber>, Weight) {
|
||||
T::NextSessionRotation::estimate_next_session_rotation(now)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> frame_support::traits::DisabledValidators for Pallet<T> {
|
||||
fn is_disabled(index: u32) -> bool {
|
||||
<Pallet<T>>::disabled_validators().binary_search(&index).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,25 +942,7 @@ impl<T: Config, Inner: FindAuthor<u32>> FindAuthor<T::ValidatorId>
|
||||
{
|
||||
let i = Inner::find_author(digests)?;
|
||||
|
||||
let validators = <Module<T>>::validators();
|
||||
let validators = <Pallet<T>>::validators();
|
||||
validators.get(i as usize).map(|k| k.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> EstimateNextNewSession<T::BlockNumber> for Module<T> {
|
||||
fn average_session_length() -> T::BlockNumber {
|
||||
T::NextSessionRotation::average_session_length()
|
||||
}
|
||||
|
||||
/// This session module always calls new_session and next_session at the same time, hence we
|
||||
/// do a simple proxy and pass the function to next rotation.
|
||||
fn estimate_next_new_session(now: T::BlockNumber) -> (Option<T::BlockNumber>, Weight) {
|
||||
T::NextSessionRotation::estimate_next_session_rotation(now)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> frame_support::traits::DisabledValidators for Module<T> {
|
||||
fn is_disabled(index: u32) -> bool {
|
||||
<Module<T>>::disabled_validators().binary_search(&index).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ use super::*;
|
||||
use crate as pallet_session;
|
||||
#[cfg(feature = "historical")]
|
||||
use crate::historical as pallet_session_historical;
|
||||
use frame_support::{parameter_types, BasicExternalities};
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use sp_core::{crypto::key_types::DUMMY, H256};
|
||||
use sp_runtime::{
|
||||
impl_opaque_keys,
|
||||
@@ -30,7 +32,8 @@ use sp_runtime::{
|
||||
Perbill,
|
||||
};
|
||||
use sp_staking::SessionIndex;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use frame_support::{parameter_types, traits::GenesisBuild, BasicExternalities};
|
||||
|
||||
impl_opaque_keys! {
|
||||
pub struct MockSessionKeys {
|
||||
|
||||
@@ -18,17 +18,19 @@
|
||||
// Tests for the Session Pallet
|
||||
|
||||
use super::*;
|
||||
use codec::Decode;
|
||||
use frame_support::{assert_noop, assert_ok, traits::OnInitialize};
|
||||
use mock::{
|
||||
use crate::mock::{
|
||||
authorities, before_session_end_called, force_new_session, new_test_ext,
|
||||
reset_before_session_end_called, session_changed, set_next_validators, set_session_length,
|
||||
Origin, PreUpgradeMockSessionKeys, Session, System, Test, SESSION_CHANGED,
|
||||
TEST_SESSION_CHANGED,
|
||||
};
|
||||
|
||||
use codec::Decode;
|
||||
use sp_core::crypto::key_types::DUMMY;
|
||||
use sp_runtime::testing::UintAuthorityId;
|
||||
|
||||
use frame_support::{assert_noop, assert_ok, traits::OnInitialize};
|
||||
|
||||
fn initialize_block(block: u64) {
|
||||
SESSION_CHANGED.with(|l| *l.borrow_mut() = false);
|
||||
System::set_block_number(block);
|
||||
|
||||
@@ -22,8 +22,7 @@ use frame_election_provider_support::{onchain, SortedListProvider};
|
||||
use frame_support::{
|
||||
assert_ok, parameter_types,
|
||||
traits::{
|
||||
Currency, FindAuthor, GenesisBuild, Get, Hooks, Imbalance, OnInitialize, OnUnbalanced,
|
||||
OneSessionHandler,
|
||||
Currency, FindAuthor, GenesisBuild, Get, Hooks, Imbalance, OnUnbalanced, OneSessionHandler,
|
||||
},
|
||||
weights::constants::RocksDbWeight,
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ use frame_support::{
|
||||
assert_noop, assert_ok,
|
||||
dispatch::WithPostDispatchInfo,
|
||||
pallet_prelude::*,
|
||||
traits::{Currency, Get, OnInitialize, ReservableCurrency},
|
||||
traits::{Currency, Get, ReservableCurrency},
|
||||
weights::{extract_actual_weight, GetDispatchInfo},
|
||||
};
|
||||
use mock::*;
|
||||
|
||||
Reference in New Issue
Block a user