mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-08-02 09:55:45 +00:00
50eb12cf2f
Moved from: https://github.com/paritytech/polkadot/pull/6951 closes https://github.com/paritytech/polkadot-sdk/issues/490 - [x] update cumulus --- This PR introduces transactional processing of certain xcm instructions. For the list of instructions checkout https://github.com/paritytech/polkadot-sdk/issues/490. The transactional processing is implemented as an xcm-executor config item. The two implementations in this PR are `FrameTransactionalProcessor` and `()`. The `()` implementation does no transactional processing. Each implementation of the `ProcessTransaction` trait has an `IS_TRANSACTIONAL` const that tells the XCVM if transactional processing is actually implemented. If Transactional processing is implemented, changes to touched registers should also be rolled back to prevent inconsistencies. Note for reviewers: Check out the following safety assumption: https://github.com/paritytech/polkadot-sdk/pull/1222/files#diff-4effad7d8c1c9de19fd27e18661cbf2128c8718f3b2420a27d2f816e0749ea53R30 --------- Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com> Co-authored-by: command-bot <>
2557 lines
86 KiB
Rust
2557 lines
86 KiB
Rust
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
// This file is part of Polkadot.
|
|
|
|
// Polkadot 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.
|
|
|
|
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! The Westend runtime. This can be compiled with `#[no_std]`, ready for Wasm.
|
|
|
|
#![cfg_attr(not(feature = "std"), no_std)]
|
|
// `construct_runtime!` does a lot of recursion and requires us to increase the limit.
|
|
#![recursion_limit = "512"]
|
|
|
|
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
|
|
use beefy_primitives::{
|
|
ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
|
|
mmr::{BeefyDataProvider, MmrLeafVersion},
|
|
};
|
|
use frame_election_provider_support::{bounds::ElectionBoundsBuilder, onchain, SequentialPhragmen};
|
|
use frame_support::{
|
|
construct_runtime, derive_impl,
|
|
genesis_builder_helper::{build_config, create_default_config},
|
|
parameter_types,
|
|
traits::{
|
|
fungible::HoldConsideration, ConstU32, Contains, EitherOf, EitherOfDiverse, EverythingBut,
|
|
InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, ProcessMessage,
|
|
ProcessMessageError, WithdrawReasons,
|
|
},
|
|
weights::{ConstantMultiplier, WeightMeter},
|
|
PalletId,
|
|
};
|
|
use frame_system::{EnsureRoot, EnsureSigned};
|
|
use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId};
|
|
use pallet_identity::legacy::IdentityInfo;
|
|
use pallet_session::historical as session_historical;
|
|
use pallet_transaction_payment::{CurrencyAdapter, FeeDetails, RuntimeDispatchInfo};
|
|
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
|
|
use primitives::{
|
|
slashing,
|
|
vstaging::{ApprovalVotingParams, NodeFeatures},
|
|
AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CandidateHash,
|
|
CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash,
|
|
Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, Moment, Nonce,
|
|
OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes,
|
|
SessionInfo, Signature, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex,
|
|
ValidatorSignature, PARACHAIN_KEY_TYPE_ID,
|
|
};
|
|
use runtime_common::{
|
|
assigned_slots, auctions, crowdloan,
|
|
elections::OnChainAccuracy,
|
|
identity_migrator, impl_runtime_weights,
|
|
impls::{
|
|
LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter,
|
|
},
|
|
paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, BalanceToU256, BlockHashCount,
|
|
BlockLength, CurrencyToVote, SlowAdjustingFeeUpdate, U256ToBalance,
|
|
};
|
|
use runtime_parachains::{
|
|
assigner_parachains as parachains_assigner_parachains,
|
|
configuration as parachains_configuration, disputes as parachains_disputes,
|
|
disputes::slashing as parachains_slashing,
|
|
dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion,
|
|
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
|
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
|
|
paras_inherent as parachains_paras_inherent, reward_points as parachains_reward_points,
|
|
runtime_api_impl::{
|
|
v7 as parachains_runtime_api_impl, vstaging as parachains_staging_runtime_api_impl,
|
|
},
|
|
scheduler as parachains_scheduler, session_info as parachains_session_info,
|
|
shared as parachains_shared,
|
|
};
|
|
use scale_info::TypeInfo;
|
|
use sp_core::{OpaqueMetadata, RuntimeDebug, H256};
|
|
use sp_runtime::{
|
|
create_runtime_str,
|
|
curve::PiecewiseLinear,
|
|
generic, impl_opaque_keys,
|
|
traits::{
|
|
BlakeTwo256, Block as BlockT, ConvertInto, Extrinsic as ExtrinsicT, IdentityLookup,
|
|
Keccak256, OpaqueKeys, SaturatedConversion, Verify,
|
|
},
|
|
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
|
|
ApplyExtrinsicResult, BoundToRuntimeAppPublic, FixedU128, KeyTypeId, Perbill, Percent, Permill,
|
|
RuntimeAppPublic,
|
|
};
|
|
use sp_staking::SessionIndex;
|
|
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
|
|
#[cfg(any(feature = "std", test))]
|
|
use sp_version::NativeVersion;
|
|
use sp_version::RuntimeVersion;
|
|
use xcm::{
|
|
latest::{InteriorLocation, Junction, Junction::PalletInstance},
|
|
VersionedLocation,
|
|
};
|
|
use xcm_builder::PayOverXcm;
|
|
|
|
pub use frame_system::Call as SystemCall;
|
|
pub use pallet_balances::Call as BalancesCall;
|
|
pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase};
|
|
#[cfg(feature = "std")]
|
|
pub use pallet_staking::StakerStatus;
|
|
use pallet_staking::UseValidatorsMap;
|
|
pub use pallet_timestamp::Call as TimestampCall;
|
|
use sp_runtime::traits::Get;
|
|
#[cfg(any(feature = "std", test))]
|
|
pub use sp_runtime::BuildStorage;
|
|
|
|
/// Constant values used within the runtime.
|
|
use westend_runtime_constants::{currency::*, fee::*, system_parachain::BROKER_ID, time::*};
|
|
|
|
mod bag_thresholds;
|
|
mod weights;
|
|
pub mod xcm_config;
|
|
|
|
// Implemented types.
|
|
mod impls;
|
|
use impls::ToParachainIdentityReaper;
|
|
|
|
// Governance and configurations.
|
|
pub mod governance;
|
|
use governance::{
|
|
pallet_custom_origins, AuctionAdmin, FellowshipAdmin, GeneralAdmin, LeaseAdmin, StakingAdmin,
|
|
Treasurer, TreasurySpender,
|
|
};
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
impl_runtime_weights!(westend_runtime_constants);
|
|
|
|
// Make the WASM binary available.
|
|
#[cfg(feature = "std")]
|
|
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
|
|
|
/// Runtime version (Westend).
|
|
#[sp_version::runtime_version]
|
|
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|
spec_name: create_runtime_str!("westend"),
|
|
impl_name: create_runtime_str!("parity-westend"),
|
|
authoring_version: 2,
|
|
spec_version: 1_006_001,
|
|
impl_version: 0,
|
|
apis: RUNTIME_API_VERSIONS,
|
|
transaction_version: 24,
|
|
state_version: 1,
|
|
};
|
|
|
|
/// The BABE epoch configuration at genesis.
|
|
pub const BABE_GENESIS_EPOCH_CONFIG: babe_primitives::BabeEpochConfiguration =
|
|
babe_primitives::BabeEpochConfiguration {
|
|
c: PRIMARY_PROBABILITY,
|
|
allowed_slots: babe_primitives::AllowedSlots::PrimaryAndSecondaryVRFSlots,
|
|
};
|
|
|
|
/// Native version.
|
|
#[cfg(any(feature = "std", test))]
|
|
pub fn native_version() -> NativeVersion {
|
|
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
|
|
}
|
|
|
|
/// A type to identify calls to the Identity pallet. These will be filtered to prevent invocation,
|
|
/// locking the state of the pallet and preventing further updates to identities and sub-identities.
|
|
/// The locked state will be the genesis state of a new system chain and then removed from the Relay
|
|
/// Chain.
|
|
pub struct IsIdentityCall;
|
|
impl Contains<RuntimeCall> for IsIdentityCall {
|
|
fn contains(c: &RuntimeCall) -> bool {
|
|
matches!(c, RuntimeCall::Identity(_))
|
|
}
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const Version: RuntimeVersion = VERSION;
|
|
pub const SS58Prefix: u8 = 42;
|
|
}
|
|
|
|
#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig as frame_system::DefaultConfig)]
|
|
impl frame_system::Config for Runtime {
|
|
type BaseCallFilter = EverythingBut<IsIdentityCall>;
|
|
type BlockWeights = BlockWeights;
|
|
type BlockLength = BlockLength;
|
|
type Nonce = Nonce;
|
|
type Hash = Hash;
|
|
type AccountId = AccountId;
|
|
type Block = Block;
|
|
type BlockHashCount = BlockHashCount;
|
|
type DbWeight = RocksDbWeight;
|
|
type Version = Version;
|
|
type AccountData = pallet_balances::AccountData<Balance>;
|
|
type SystemWeightInfo = weights::frame_system::WeightInfo<Runtime>;
|
|
type SS58Prefix = SS58Prefix;
|
|
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub MaximumSchedulerWeight: frame_support::weights::Weight = Perbill::from_percent(80) *
|
|
BlockWeights::get().max_block;
|
|
pub const MaxScheduledPerBlock: u32 = 50;
|
|
pub const NoPreimagePostponement: Option<u32> = Some(10);
|
|
}
|
|
|
|
impl pallet_scheduler::Config for Runtime {
|
|
type RuntimeOrigin = RuntimeOrigin;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type PalletsOrigin = OriginCaller;
|
|
type RuntimeCall = RuntimeCall;
|
|
type MaximumWeight = MaximumSchedulerWeight;
|
|
// The goal of having ScheduleOrigin include AuctionAdmin is to allow the auctions track of
|
|
// OpenGov to schedule periodic auctions.
|
|
type ScheduleOrigin = EitherOf<EnsureRoot<AccountId>, AuctionAdmin>;
|
|
type MaxScheduledPerBlock = MaxScheduledPerBlock;
|
|
type WeightInfo = weights::pallet_scheduler::WeightInfo<Runtime>;
|
|
type OriginPrivilegeCmp = frame_support::traits::EqualPrivilegeOnly;
|
|
type Preimages = Preimage;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const PreimageBaseDeposit: Balance = deposit(2, 64);
|
|
pub const PreimageByteDeposit: Balance = deposit(0, 1);
|
|
pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
|
|
}
|
|
|
|
impl pallet_preimage::Config for Runtime {
|
|
type WeightInfo = weights::pallet_preimage::WeightInfo<Runtime>;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type ManagerOrigin = EnsureRoot<AccountId>;
|
|
type Consideration = HoldConsideration<
|
|
AccountId,
|
|
Balances,
|
|
PreimageHoldReason,
|
|
LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
|
|
>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const EpochDuration: u64 = prod_or_fast!(
|
|
EPOCH_DURATION_IN_SLOTS as u64,
|
|
2 * MINUTES as u64
|
|
);
|
|
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
|
|
pub const ReportLongevity: u64 =
|
|
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get();
|
|
}
|
|
|
|
impl pallet_babe::Config for Runtime {
|
|
type EpochDuration = EpochDuration;
|
|
type ExpectedBlockTime = ExpectedBlockTime;
|
|
|
|
// session module is the trigger
|
|
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
|
|
|
|
type DisabledValidators = Session;
|
|
|
|
type WeightInfo = ();
|
|
|
|
type MaxAuthorities = MaxAuthorities;
|
|
type MaxNominators = MaxNominators;
|
|
|
|
type KeyOwnerProof = sp_session::MembershipProof;
|
|
|
|
type EquivocationReportSystem =
|
|
pallet_babe::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const IndexDeposit: Balance = 100 * CENTS;
|
|
}
|
|
|
|
impl pallet_indices::Config for Runtime {
|
|
type AccountIndex = AccountIndex;
|
|
type Currency = Balances;
|
|
type Deposit = IndexDeposit;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type WeightInfo = weights::pallet_indices::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
|
|
pub const MaxLocks: u32 = 50;
|
|
pub const MaxReserves: u32 = 50;
|
|
}
|
|
|
|
impl pallet_balances::Config for Runtime {
|
|
type Balance = Balance;
|
|
type DustRemoval = ();
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type ExistentialDeposit = ExistentialDeposit;
|
|
type AccountStore = System;
|
|
type MaxLocks = MaxLocks;
|
|
type MaxReserves = MaxReserves;
|
|
type ReserveIdentifier = [u8; 8];
|
|
type WeightInfo = weights::pallet_balances::WeightInfo<Runtime>;
|
|
type RuntimeHoldReason = RuntimeHoldReason;
|
|
type RuntimeFreezeReason = RuntimeFreezeReason;
|
|
type FreezeIdentifier = RuntimeFreezeReason;
|
|
type MaxFreezes = ConstU32<1>;
|
|
type MaxHolds = ConstU32<1>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const BeefySetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get();
|
|
}
|
|
|
|
impl pallet_beefy::Config for Runtime {
|
|
type BeefyId = BeefyId;
|
|
type MaxAuthorities = MaxAuthorities;
|
|
type MaxNominators = MaxNominators;
|
|
type MaxSetIdSessionEntries = BeefySetIdSessionEntries;
|
|
type OnNewValidatorSet = BeefyMmrLeaf;
|
|
type WeightInfo = ();
|
|
type KeyOwnerProof = sp_session::MembershipProof;
|
|
type EquivocationReportSystem =
|
|
pallet_beefy::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
|
|
}
|
|
|
|
impl pallet_mmr::Config for Runtime {
|
|
const INDEXING_PREFIX: &'static [u8] = mmr::INDEXING_PREFIX;
|
|
type Hashing = Keccak256;
|
|
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
|
|
type WeightInfo = ();
|
|
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
|
|
}
|
|
|
|
/// MMR helper types.
|
|
mod mmr {
|
|
use super::Runtime;
|
|
pub use pallet_mmr::primitives::*;
|
|
|
|
pub type Leaf = <<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider>::LeafData;
|
|
pub type Hashing = <Runtime as pallet_mmr::Config>::Hashing;
|
|
pub type Hash = <Hashing as sp_runtime::traits::Hash>::Output;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
|
|
}
|
|
|
|
/// A BEEFY data provider that merkelizes all the parachain heads at the current block
|
|
/// (sorted by their parachain id).
|
|
pub struct ParaHeadsRootProvider;
|
|
impl BeefyDataProvider<H256> for ParaHeadsRootProvider {
|
|
fn extra_data() -> H256 {
|
|
let mut para_heads: Vec<(u32, Vec<u8>)> = Paras::parachains()
|
|
.into_iter()
|
|
.filter_map(|id| Paras::para_head(&id).map(|head| (id.into(), head.0)))
|
|
.collect();
|
|
para_heads.sort_by_key(|k| k.0);
|
|
binary_merkle_tree::merkle_root::<mmr::Hashing, _>(
|
|
para_heads.into_iter().map(|pair| pair.encode()),
|
|
)
|
|
.into()
|
|
}
|
|
}
|
|
|
|
impl pallet_beefy_mmr::Config for Runtime {
|
|
type LeafVersion = LeafVersion;
|
|
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
|
|
type LeafExtra = H256;
|
|
type BeefyDataProvider = ParaHeadsRootProvider;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
|
|
/// This value increases the priority of `Operational` transactions by adding
|
|
/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
|
|
pub const OperationalFeeMultiplier: u8 = 5;
|
|
}
|
|
|
|
impl pallet_transaction_payment::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type OnChargeTransaction = CurrencyAdapter<Balances, ToAuthor<Runtime>>;
|
|
type OperationalFeeMultiplier = OperationalFeeMultiplier;
|
|
type WeightToFee = WeightToFee;
|
|
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
|
|
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
|
|
}
|
|
impl pallet_timestamp::Config for Runtime {
|
|
type Moment = u64;
|
|
type OnTimestampSet = Babe;
|
|
type MinimumPeriod = MinimumPeriod;
|
|
type WeightInfo = weights::pallet_timestamp::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl pallet_authorship::Config for Runtime {
|
|
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
|
|
type EventHandler = Staking;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const Period: BlockNumber = 10 * MINUTES;
|
|
pub const Offset: BlockNumber = 0;
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)]
|
|
pub struct OldSessionKeys {
|
|
pub grandpa: <Grandpa as BoundToRuntimeAppPublic>::Public,
|
|
pub babe: <Babe as BoundToRuntimeAppPublic>::Public,
|
|
pub im_online: pallet_im_online::sr25519::AuthorityId,
|
|
pub para_validator: <Initializer as BoundToRuntimeAppPublic>::Public,
|
|
pub para_assignment: <ParaSessionInfo as BoundToRuntimeAppPublic>::Public,
|
|
pub authority_discovery: <AuthorityDiscovery as BoundToRuntimeAppPublic>::Public,
|
|
pub beefy: <Beefy as BoundToRuntimeAppPublic>::Public,
|
|
}
|
|
|
|
impl OpaqueKeys for OldSessionKeys {
|
|
type KeyTypeIdProviders = ();
|
|
fn key_ids() -> &'static [KeyTypeId] {
|
|
&[
|
|
<<Grandpa as BoundToRuntimeAppPublic>::Public>::ID,
|
|
<<Babe as BoundToRuntimeAppPublic>::Public>::ID,
|
|
sp_core::crypto::key_types::IM_ONLINE,
|
|
<<Initializer as BoundToRuntimeAppPublic>::Public>::ID,
|
|
<<ParaSessionInfo as BoundToRuntimeAppPublic>::Public>::ID,
|
|
<<AuthorityDiscovery as BoundToRuntimeAppPublic>::Public>::ID,
|
|
<<Beefy as BoundToRuntimeAppPublic>::Public>::ID,
|
|
]
|
|
}
|
|
fn get_raw(&self, i: KeyTypeId) -> &[u8] {
|
|
match i {
|
|
<<Grandpa as BoundToRuntimeAppPublic>::Public>::ID => self.grandpa.as_ref(),
|
|
<<Babe as BoundToRuntimeAppPublic>::Public>::ID => self.babe.as_ref(),
|
|
sp_core::crypto::key_types::IM_ONLINE => self.im_online.as_ref(),
|
|
<<Initializer as BoundToRuntimeAppPublic>::Public>::ID => self.para_validator.as_ref(),
|
|
<<ParaSessionInfo as BoundToRuntimeAppPublic>::Public>::ID =>
|
|
self.para_assignment.as_ref(),
|
|
<<AuthorityDiscovery as BoundToRuntimeAppPublic>::Public>::ID =>
|
|
self.authority_discovery.as_ref(),
|
|
<<Beefy as BoundToRuntimeAppPublic>::Public>::ID => self.beefy.as_ref(),
|
|
_ => &[],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl_opaque_keys! {
|
|
pub struct SessionKeys {
|
|
pub grandpa: Grandpa,
|
|
pub babe: Babe,
|
|
pub para_validator: Initializer,
|
|
pub para_assignment: ParaSessionInfo,
|
|
pub authority_discovery: AuthorityDiscovery,
|
|
pub beefy: Beefy,
|
|
}
|
|
}
|
|
|
|
// remove this when removing `OldSessionKeys`
|
|
fn transform_session_keys(_v: AccountId, old: OldSessionKeys) -> SessionKeys {
|
|
SessionKeys {
|
|
grandpa: old.grandpa,
|
|
babe: old.babe,
|
|
para_validator: old.para_validator,
|
|
para_assignment: old.para_assignment,
|
|
authority_discovery: old.authority_discovery,
|
|
beefy: old.beefy,
|
|
}
|
|
}
|
|
|
|
impl pallet_session::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type ValidatorId = AccountId;
|
|
type ValidatorIdOf = pallet_staking::StashOf<Self>;
|
|
type ShouldEndSession = Babe;
|
|
type NextSessionRotation = Babe;
|
|
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, Staking>;
|
|
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
|
|
type Keys = SessionKeys;
|
|
type WeightInfo = weights::pallet_session::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl pallet_session::historical::Config for Runtime {
|
|
type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
|
|
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
|
|
}
|
|
|
|
pub struct MaybeSignedPhase;
|
|
|
|
impl Get<u32> for MaybeSignedPhase {
|
|
fn get() -> u32 {
|
|
// 1 day = 4 eras -> 1 week = 28 eras. We want to disable signed phase once a week to test
|
|
// the fallback unsigned phase is able to compute elections on Westend.
|
|
if Staking::current_era().unwrap_or(1) % 28 == 0 {
|
|
0
|
|
} else {
|
|
SignedPhase::get()
|
|
}
|
|
}
|
|
}
|
|
|
|
parameter_types! {
|
|
// phase durations. 1/4 of the last session for each.
|
|
pub SignedPhase: u32 = prod_or_fast!(
|
|
EPOCH_DURATION_IN_SLOTS / 4,
|
|
(1 * MINUTES).min(EpochDuration::get().saturated_into::<u32>() / 2)
|
|
);
|
|
pub UnsignedPhase: u32 = prod_or_fast!(
|
|
EPOCH_DURATION_IN_SLOTS / 4,
|
|
(1 * MINUTES).min(EpochDuration::get().saturated_into::<u32>() / 2)
|
|
);
|
|
|
|
// signed config
|
|
pub const SignedMaxSubmissions: u32 = 128;
|
|
pub const SignedMaxRefunds: u32 = 128 / 4;
|
|
pub const SignedFixedDeposit: Balance = deposit(2, 0);
|
|
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
|
|
pub const SignedDepositByte: Balance = deposit(0, 10) / 1024;
|
|
// Each good submission will get 1 WND as reward
|
|
pub SignedRewardBase: Balance = 1 * UNITS;
|
|
|
|
// 1 hour session, 15 minutes unsigned phase, 4 offchain executions.
|
|
pub OffchainRepeat: BlockNumber = UnsignedPhase::get() / 4;
|
|
|
|
pub const MaxElectingVoters: u32 = 22_500;
|
|
/// We take the top 22500 nominators as electing voters and all of the validators as electable
|
|
/// targets. Whilst this is the case, we cannot and shall not increase the size of the
|
|
/// validator intentions.
|
|
pub ElectionBounds: frame_election_provider_support::bounds::ElectionBounds =
|
|
ElectionBoundsBuilder::default().voters_count(MaxElectingVoters::get().into()).build();
|
|
// Maximum winners that can be chosen as active validators
|
|
pub const MaxActiveValidators: u32 = 1000;
|
|
|
|
}
|
|
|
|
frame_election_provider_support::generate_solution_type!(
|
|
#[compact]
|
|
pub struct NposCompactSolution16::<
|
|
VoterIndex = u32,
|
|
TargetIndex = u16,
|
|
Accuracy = sp_runtime::PerU16,
|
|
MaxVoters = MaxElectingVoters,
|
|
>(16)
|
|
);
|
|
|
|
pub struct OnChainSeqPhragmen;
|
|
impl onchain::Config for OnChainSeqPhragmen {
|
|
type System = Runtime;
|
|
type Solver = SequentialPhragmen<AccountId, OnChainAccuracy>;
|
|
type DataProvider = Staking;
|
|
type WeightInfo = weights::frame_election_provider_support::WeightInfo<Runtime>;
|
|
type MaxWinners = MaxActiveValidators;
|
|
type Bounds = ElectionBounds;
|
|
}
|
|
|
|
impl pallet_election_provider_multi_phase::MinerConfig for Runtime {
|
|
type AccountId = AccountId;
|
|
type MaxLength = OffchainSolutionLengthLimit;
|
|
type MaxWeight = OffchainSolutionWeightLimit;
|
|
type Solution = NposCompactSolution16;
|
|
type MaxVotesPerVoter = <
|
|
<Self as pallet_election_provider_multi_phase::Config>::DataProvider
|
|
as
|
|
frame_election_provider_support::ElectionDataProvider
|
|
>::MaxVotesPerVoter;
|
|
type MaxWinners = MaxActiveValidators;
|
|
|
|
// The unsigned submissions have to respect the weight of the submit_unsigned call, thus their
|
|
// weight estimate function is wired to this call's weight.
|
|
fn solution_weight(v: u32, t: u32, a: u32, d: u32) -> Weight {
|
|
<
|
|
<Self as pallet_election_provider_multi_phase::Config>::WeightInfo
|
|
as
|
|
pallet_election_provider_multi_phase::WeightInfo
|
|
>::submit_unsigned(v, t, a, d)
|
|
}
|
|
}
|
|
|
|
impl pallet_election_provider_multi_phase::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type EstimateCallFee = TransactionPayment;
|
|
type SignedPhase = MaybeSignedPhase;
|
|
type UnsignedPhase = UnsignedPhase;
|
|
type SignedMaxSubmissions = SignedMaxSubmissions;
|
|
type SignedMaxRefunds = SignedMaxRefunds;
|
|
type SignedRewardBase = SignedRewardBase;
|
|
type SignedDepositBase =
|
|
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
|
|
type SignedDepositByte = SignedDepositByte;
|
|
type SignedDepositWeight = ();
|
|
type SignedMaxWeight =
|
|
<Self::MinerConfig as pallet_election_provider_multi_phase::MinerConfig>::MaxWeight;
|
|
type MinerConfig = Self;
|
|
type SlashHandler = (); // burn slashes
|
|
type RewardHandler = (); // nothing to do upon rewards
|
|
type BetterSignedThreshold = ();
|
|
type OffchainRepeat = OffchainRepeat;
|
|
type MinerTxPriority = NposSolutionPriority;
|
|
type DataProvider = Staking;
|
|
#[cfg(any(feature = "fast-runtime", feature = "runtime-benchmarks"))]
|
|
type Fallback = onchain::OnChainExecution<OnChainSeqPhragmen>;
|
|
#[cfg(not(any(feature = "fast-runtime", feature = "runtime-benchmarks")))]
|
|
type Fallback = frame_election_provider_support::NoElection<(
|
|
AccountId,
|
|
BlockNumber,
|
|
Staking,
|
|
MaxActiveValidators,
|
|
)>;
|
|
type GovernanceFallback = onchain::OnChainExecution<OnChainSeqPhragmen>;
|
|
type Solver = SequentialPhragmen<
|
|
AccountId,
|
|
pallet_election_provider_multi_phase::SolutionAccuracyOf<Self>,
|
|
(),
|
|
>;
|
|
type BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
|
type ForceOrigin = EnsureRoot<AccountId>;
|
|
type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo<Self>;
|
|
type MaxWinners = MaxActiveValidators;
|
|
type ElectionBounds = ElectionBounds;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const BagThresholds: &'static [u64] = &bag_thresholds::THRESHOLDS;
|
|
}
|
|
|
|
type VoterBagsListInstance = pallet_bags_list::Instance1;
|
|
impl pallet_bags_list::Config<VoterBagsListInstance> for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type ScoreProvider = Staking;
|
|
type WeightInfo = weights::pallet_bags_list::WeightInfo<Runtime>;
|
|
type BagThresholds = BagThresholds;
|
|
type Score = sp_npos_elections::VoteWeight;
|
|
}
|
|
|
|
pallet_staking_reward_curve::build! {
|
|
const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
|
|
min_inflation: 0_025_000,
|
|
max_inflation: 0_100_000,
|
|
ideal_stake: 0_500_000,
|
|
falloff: 0_050_000,
|
|
max_piece_count: 40,
|
|
test_precision: 0_005_000,
|
|
);
|
|
}
|
|
|
|
parameter_types! {
|
|
// Six sessions in an era (6 hours).
|
|
pub const SessionsPerEra: SessionIndex = prod_or_fast!(6, 1);
|
|
// 2 eras for unbonding (12 hours).
|
|
pub const BondingDuration: sp_staking::EraIndex = 2;
|
|
// 1 era in which slashes can be cancelled (6 hours).
|
|
pub const SlashDeferDuration: sp_staking::EraIndex = 1;
|
|
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
|
|
pub const MaxExposurePageSize: u32 = 64;
|
|
// Note: this is not really correct as Max Nominators is (MaxExposurePageSize * page_count) but
|
|
// this is an unbounded number. We just set it to a reasonably high value, 1 full page
|
|
// of nominators.
|
|
pub const MaxNominators: u32 = 64;
|
|
pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17);
|
|
pub const MaxNominations: u32 = <NposCompactSolution16 as frame_election_provider_support::NposSolution>::LIMIT as u32;
|
|
pub const MaxControllersInDeprecationBatch: u32 = 751;
|
|
}
|
|
|
|
impl pallet_staking::Config for Runtime {
|
|
type Currency = Balances;
|
|
type CurrencyBalance = Balance;
|
|
type UnixTime = Timestamp;
|
|
type CurrencyToVote = CurrencyToVote;
|
|
type RewardRemainder = ();
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Slash = ();
|
|
type Reward = ();
|
|
type SessionsPerEra = SessionsPerEra;
|
|
type BondingDuration = BondingDuration;
|
|
type SlashDeferDuration = SlashDeferDuration;
|
|
type AdminOrigin = EitherOf<EnsureRoot<AccountId>, StakingAdmin>;
|
|
type SessionInterface = Self;
|
|
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
|
|
type MaxExposurePageSize = MaxExposurePageSize;
|
|
type OffendingValidatorsThreshold = OffendingValidatorsThreshold;
|
|
type NextNewSession = Session;
|
|
type ElectionProvider = ElectionProviderMultiPhase;
|
|
type GenesisElectionProvider = onchain::OnChainExecution<OnChainSeqPhragmen>;
|
|
type VoterList = VoterList;
|
|
type TargetList = UseValidatorsMap<Self>;
|
|
type NominationsQuota = pallet_staking::FixedNominationsQuota<{ MaxNominations::get() }>;
|
|
type MaxUnlockingChunks = frame_support::traits::ConstU32<32>;
|
|
type HistoryDepth = frame_support::traits::ConstU32<84>;
|
|
type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch;
|
|
type BenchmarkingConfig = runtime_common::StakingBenchmarkingConfig;
|
|
type EventListeners = NominationPools;
|
|
type WeightInfo = weights::pallet_staking::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl pallet_fast_unstake::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type BatchSize = frame_support::traits::ConstU32<64>;
|
|
type Deposit = frame_support::traits::ConstU128<{ UNITS }>;
|
|
type ControlOrigin = EnsureRoot<AccountId>;
|
|
type Staking = Staking;
|
|
type MaxErasToCheckPerBlock = ConstU32<1>;
|
|
type WeightInfo = weights::pallet_fast_unstake::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const ProposalBond: Permill = Permill::from_percent(5);
|
|
pub const ProposalBondMinimum: Balance = 2000 * CENTS;
|
|
pub const ProposalBondMaximum: Balance = 1 * GRAND;
|
|
pub const SpendPeriod: BlockNumber = 6 * DAYS;
|
|
pub const Burn: Permill = Permill::from_perthousand(2);
|
|
pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
|
|
pub const PayoutSpendPeriod: BlockNumber = 30 * DAYS;
|
|
// The asset's interior location for the paying account. This is the Treasury
|
|
// pallet instance (which sits at index 37).
|
|
pub TreasuryInteriorLocation: InteriorLocation = PalletInstance(37).into();
|
|
|
|
pub const TipCountdown: BlockNumber = 1 * DAYS;
|
|
pub const TipFindersFee: Percent = Percent::from_percent(20);
|
|
pub const TipReportDepositBase: Balance = 100 * CENTS;
|
|
pub const DataDepositPerByte: Balance = 1 * CENTS;
|
|
pub const MaxApprovals: u32 = 100;
|
|
pub const MaxAuthorities: u32 = 100_000;
|
|
pub const MaxKeys: u32 = 10_000;
|
|
pub const MaxPeerInHeartbeats: u32 = 10_000;
|
|
pub const MaxBalance: Balance = Balance::max_value();
|
|
}
|
|
|
|
impl pallet_treasury::Config for Runtime {
|
|
type PalletId = TreasuryPalletId;
|
|
type Currency = Balances;
|
|
type ApproveOrigin = EitherOfDiverse<EnsureRoot<AccountId>, Treasurer>;
|
|
type RejectOrigin = EitherOfDiverse<EnsureRoot<AccountId>, Treasurer>;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type OnSlash = Treasury;
|
|
type ProposalBond = ProposalBond;
|
|
type ProposalBondMinimum = ProposalBondMinimum;
|
|
type ProposalBondMaximum = ProposalBondMaximum;
|
|
type SpendPeriod = SpendPeriod;
|
|
type Burn = Burn;
|
|
type BurnDestination = ();
|
|
type MaxApprovals = MaxApprovals;
|
|
type WeightInfo = weights::pallet_treasury::WeightInfo<Runtime>;
|
|
type SpendFunds = ();
|
|
type SpendOrigin = TreasurySpender;
|
|
type AssetKind = VersionedLocatableAsset;
|
|
type Beneficiary = VersionedLocation;
|
|
type BeneficiaryLookup = IdentityLookup<Self::Beneficiary>;
|
|
type Paymaster = PayOverXcm<
|
|
TreasuryInteriorLocation,
|
|
crate::xcm_config::XcmRouter,
|
|
crate::XcmPallet,
|
|
ConstU32<{ 6 * HOURS }>,
|
|
Self::Beneficiary,
|
|
Self::AssetKind,
|
|
LocatableAssetConverter,
|
|
VersionedLocationConverter,
|
|
>;
|
|
type BalanceConverter = AssetRate;
|
|
type PayoutPeriod = PayoutSpendPeriod;
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
type BenchmarkHelper = runtime_common::impls::benchmarks::TreasuryArguments;
|
|
}
|
|
|
|
impl pallet_offences::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type IdentificationTuple = pallet_session::historical::IdentificationTuple<Self>;
|
|
type OnOffenceHandler = Staking;
|
|
}
|
|
|
|
impl pallet_authority_discovery::Config for Runtime {
|
|
type MaxAuthorities = MaxAuthorities;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const NposSolutionPriority: TransactionPriority = TransactionPriority::max_value() / 2;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const MaxSetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get();
|
|
}
|
|
|
|
impl pallet_grandpa::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
|
|
type WeightInfo = ();
|
|
type MaxAuthorities = MaxAuthorities;
|
|
type MaxNominators = MaxNominators;
|
|
type MaxSetIdSessionEntries = MaxSetIdSessionEntries;
|
|
|
|
type KeyOwnerProof = sp_session::MembershipProof;
|
|
|
|
type EquivocationReportSystem =
|
|
pallet_grandpa::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
|
|
}
|
|
|
|
/// Submits a transaction with the node's public and signature type. Adheres to the signed extension
|
|
/// format of the chain.
|
|
impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
|
|
where
|
|
RuntimeCall: From<LocalCall>,
|
|
{
|
|
fn create_transaction<C: frame_system::offchain::AppCrypto<Self::Public, Self::Signature>>(
|
|
call: RuntimeCall,
|
|
public: <Signature as Verify>::Signer,
|
|
account: AccountId,
|
|
nonce: <Runtime as frame_system::Config>::Nonce,
|
|
) -> Option<(RuntimeCall, <UncheckedExtrinsic as ExtrinsicT>::SignaturePayload)> {
|
|
use sp_runtime::traits::StaticLookup;
|
|
// take the biggest period possible.
|
|
let period =
|
|
BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
|
|
|
|
let current_block = System::block_number()
|
|
.saturated_into::<u64>()
|
|
// The `System::block_number` is initialized with `n+1`,
|
|
// so the actual block number is `n`.
|
|
.saturating_sub(1);
|
|
let tip = 0;
|
|
let extra: SignedExtra = (
|
|
frame_system::CheckNonZeroSender::<Runtime>::new(),
|
|
frame_system::CheckSpecVersion::<Runtime>::new(),
|
|
frame_system::CheckTxVersion::<Runtime>::new(),
|
|
frame_system::CheckGenesis::<Runtime>::new(),
|
|
frame_system::CheckMortality::<Runtime>::from(generic::Era::mortal(
|
|
period,
|
|
current_block,
|
|
)),
|
|
frame_system::CheckNonce::<Runtime>::from(nonce),
|
|
frame_system::CheckWeight::<Runtime>::new(),
|
|
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
|
|
);
|
|
let raw_payload = SignedPayload::new(call, extra)
|
|
.map_err(|e| {
|
|
log::warn!("Unable to create signed payload: {:?}", e);
|
|
})
|
|
.ok()?;
|
|
let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
|
|
let (call, extra, _) = raw_payload.deconstruct();
|
|
let address = <Runtime as frame_system::Config>::Lookup::unlookup(account);
|
|
Some((call, (address, signature, extra)))
|
|
}
|
|
}
|
|
|
|
impl frame_system::offchain::SigningTypes for Runtime {
|
|
type Public = <Signature as Verify>::Signer;
|
|
type Signature = Signature;
|
|
}
|
|
|
|
impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime
|
|
where
|
|
RuntimeCall: From<C>,
|
|
{
|
|
type OverarchingCall = RuntimeCall;
|
|
type Extrinsic = UncheckedExtrinsic;
|
|
}
|
|
|
|
parameter_types! {
|
|
// Minimum 100 bytes/KSM deposited (1 CENT/byte)
|
|
pub const BasicDeposit: Balance = 1000 * CENTS; // 258 bytes on-chain
|
|
pub const ByteDeposit: Balance = deposit(0, 1);
|
|
pub const SubAccountDeposit: Balance = 200 * CENTS; // 53 bytes on-chain
|
|
pub const MaxSubAccounts: u32 = 100;
|
|
pub const MaxAdditionalFields: u32 = 100;
|
|
pub const MaxRegistrars: u32 = 20;
|
|
}
|
|
|
|
impl pallet_identity::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type Slashed = ();
|
|
type BasicDeposit = BasicDeposit;
|
|
type ByteDeposit = ByteDeposit;
|
|
type SubAccountDeposit = SubAccountDeposit;
|
|
type MaxSubAccounts = MaxSubAccounts;
|
|
type IdentityInformation = IdentityInfo<MaxAdditionalFields>;
|
|
type MaxRegistrars = MaxRegistrars;
|
|
type ForceOrigin = EitherOf<EnsureRoot<Self::AccountId>, GeneralAdmin>;
|
|
type RegistrarOrigin = EitherOf<EnsureRoot<Self::AccountId>, GeneralAdmin>;
|
|
type OffchainSignature = Signature;
|
|
type SigningPublicKey = <Signature as Verify>::Signer;
|
|
type UsernameAuthorityOrigin = EnsureRoot<Self::AccountId>;
|
|
type PendingUsernameExpiration = ConstU32<{ 7 * DAYS }>;
|
|
type MaxSuffixLength = ConstU32<7>;
|
|
type MaxUsernameLength = ConstU32<32>;
|
|
type WeightInfo = weights::pallet_identity::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl pallet_utility::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type RuntimeCall = RuntimeCall;
|
|
type PalletsOrigin = OriginCaller;
|
|
type WeightInfo = weights::pallet_utility::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
// One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
|
|
pub const DepositBase: Balance = deposit(1, 88);
|
|
// Additional storage item size of 32 bytes.
|
|
pub const DepositFactor: Balance = deposit(0, 32);
|
|
pub const MaxSignatories: u32 = 100;
|
|
}
|
|
|
|
impl pallet_multisig::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type RuntimeCall = RuntimeCall;
|
|
type Currency = Balances;
|
|
type DepositBase = DepositBase;
|
|
type DepositFactor = DepositFactor;
|
|
type MaxSignatories = MaxSignatories;
|
|
type WeightInfo = weights::pallet_multisig::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const ConfigDepositBase: Balance = 500 * CENTS;
|
|
pub const FriendDepositFactor: Balance = 50 * CENTS;
|
|
pub const MaxFriends: u16 = 9;
|
|
pub const RecoveryDeposit: Balance = 500 * CENTS;
|
|
}
|
|
|
|
impl pallet_recovery::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type WeightInfo = ();
|
|
type RuntimeCall = RuntimeCall;
|
|
type Currency = Balances;
|
|
type ConfigDepositBase = ConfigDepositBase;
|
|
type FriendDepositFactor = FriendDepositFactor;
|
|
type MaxFriends = MaxFriends;
|
|
type RecoveryDeposit = RecoveryDeposit;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const MinVestedTransfer: Balance = 100 * CENTS;
|
|
pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
|
|
WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
|
|
}
|
|
|
|
impl pallet_vesting::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type BlockNumberToBalance = ConvertInto;
|
|
type MinVestedTransfer = MinVestedTransfer;
|
|
type WeightInfo = weights::pallet_vesting::WeightInfo<Runtime>;
|
|
type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
|
|
type BlockNumberProvider = System;
|
|
const MAX_VESTING_SCHEDULES: u32 = 28;
|
|
}
|
|
|
|
impl pallet_sudo::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type RuntimeCall = RuntimeCall;
|
|
type WeightInfo = weights::pallet_sudo::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
// One storage item; key size 32, value size 8; .
|
|
pub const ProxyDepositBase: Balance = deposit(1, 8);
|
|
// Additional storage item size of 33 bytes.
|
|
pub const ProxyDepositFactor: Balance = deposit(0, 33);
|
|
pub const MaxProxies: u16 = 32;
|
|
pub const AnnouncementDepositBase: Balance = deposit(1, 8);
|
|
pub const AnnouncementDepositFactor: Balance = deposit(0, 66);
|
|
pub const MaxPending: u16 = 32;
|
|
}
|
|
|
|
/// The type used to represent the kinds of proxying allowed.
|
|
#[derive(
|
|
Copy,
|
|
Clone,
|
|
Eq,
|
|
PartialEq,
|
|
Ord,
|
|
PartialOrd,
|
|
Encode,
|
|
Decode,
|
|
RuntimeDebug,
|
|
MaxEncodedLen,
|
|
TypeInfo,
|
|
)]
|
|
pub enum ProxyType {
|
|
Any,
|
|
NonTransfer,
|
|
Governance,
|
|
Staking,
|
|
SudoBalances,
|
|
IdentityJudgement,
|
|
CancelProxy,
|
|
Auction,
|
|
NominationPools,
|
|
}
|
|
impl Default for ProxyType {
|
|
fn default() -> Self {
|
|
Self::Any
|
|
}
|
|
}
|
|
impl InstanceFilter<RuntimeCall> for ProxyType {
|
|
fn filter(&self, c: &RuntimeCall) -> bool {
|
|
match self {
|
|
ProxyType::Any => true,
|
|
ProxyType::NonTransfer => matches!(
|
|
c,
|
|
RuntimeCall::System(..) |
|
|
RuntimeCall::Babe(..) |
|
|
RuntimeCall::Timestamp(..) |
|
|
RuntimeCall::Indices(pallet_indices::Call::claim{..}) |
|
|
RuntimeCall::Indices(pallet_indices::Call::free{..}) |
|
|
RuntimeCall::Indices(pallet_indices::Call::freeze{..}) |
|
|
// Specifically omitting Indices `transfer`, `force_transfer`
|
|
// Specifically omitting the entire Balances pallet
|
|
RuntimeCall::Staking(..) |
|
|
RuntimeCall::Session(..) |
|
|
RuntimeCall::Grandpa(..) |
|
|
RuntimeCall::Utility(..) |
|
|
RuntimeCall::Identity(..) |
|
|
RuntimeCall::ConvictionVoting(..) |
|
|
RuntimeCall::Referenda(..) |
|
|
RuntimeCall::Whitelist(..) |
|
|
RuntimeCall::Recovery(pallet_recovery::Call::as_recovered{..}) |
|
|
RuntimeCall::Recovery(pallet_recovery::Call::vouch_recovery{..}) |
|
|
RuntimeCall::Recovery(pallet_recovery::Call::claim_recovery{..}) |
|
|
RuntimeCall::Recovery(pallet_recovery::Call::close_recovery{..}) |
|
|
RuntimeCall::Recovery(pallet_recovery::Call::remove_recovery{..}) |
|
|
RuntimeCall::Recovery(pallet_recovery::Call::cancel_recovered{..}) |
|
|
// Specifically omitting Recovery `create_recovery`, `initiate_recovery`
|
|
RuntimeCall::Vesting(pallet_vesting::Call::vest{..}) |
|
|
RuntimeCall::Vesting(pallet_vesting::Call::vest_other{..}) |
|
|
// Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer`
|
|
RuntimeCall::Scheduler(..) |
|
|
// Specifically omitting Sudo pallet
|
|
RuntimeCall::Proxy(..) |
|
|
RuntimeCall::Multisig(..) |
|
|
RuntimeCall::Registrar(paras_registrar::Call::register{..}) |
|
|
RuntimeCall::Registrar(paras_registrar::Call::deregister{..}) |
|
|
// Specifically omitting Registrar `swap`
|
|
RuntimeCall::Registrar(paras_registrar::Call::reserve{..}) |
|
|
RuntimeCall::Crowdloan(..) |
|
|
RuntimeCall::Slots(..) |
|
|
RuntimeCall::Auctions(..) | // Specifically omitting the entire XCM Pallet
|
|
RuntimeCall::VoterList(..) |
|
|
RuntimeCall::NominationPools(..) |
|
|
RuntimeCall::FastUnstake(..)
|
|
),
|
|
ProxyType::Staking => {
|
|
matches!(
|
|
c,
|
|
RuntimeCall::Staking(..) |
|
|
RuntimeCall::Session(..) | RuntimeCall::Utility(..) |
|
|
RuntimeCall::FastUnstake(..) |
|
|
RuntimeCall::VoterList(..) |
|
|
RuntimeCall::NominationPools(..)
|
|
)
|
|
},
|
|
ProxyType::NominationPools => {
|
|
matches!(c, RuntimeCall::NominationPools(..) | RuntimeCall::Utility(..))
|
|
},
|
|
ProxyType::SudoBalances => match c {
|
|
RuntimeCall::Sudo(pallet_sudo::Call::sudo { call: ref x }) => {
|
|
matches!(x.as_ref(), &RuntimeCall::Balances(..))
|
|
},
|
|
RuntimeCall::Utility(..) => true,
|
|
_ => false,
|
|
},
|
|
ProxyType::Governance => matches!(
|
|
c,
|
|
// OpenGov calls
|
|
RuntimeCall::ConvictionVoting(..) |
|
|
RuntimeCall::Referenda(..) |
|
|
RuntimeCall::Whitelist(..)
|
|
),
|
|
ProxyType::IdentityJudgement => matches!(
|
|
c,
|
|
RuntimeCall::Identity(pallet_identity::Call::provide_judgement { .. }) |
|
|
RuntimeCall::Utility(..)
|
|
),
|
|
ProxyType::CancelProxy => {
|
|
matches!(c, RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }))
|
|
},
|
|
ProxyType::Auction => matches!(
|
|
c,
|
|
RuntimeCall::Auctions(..) |
|
|
RuntimeCall::Crowdloan(..) |
|
|
RuntimeCall::Registrar(..) |
|
|
RuntimeCall::Slots(..)
|
|
),
|
|
}
|
|
}
|
|
fn is_superset(&self, o: &Self) -> bool {
|
|
match (self, o) {
|
|
(x, y) if x == y => true,
|
|
(ProxyType::Any, _) => true,
|
|
(_, ProxyType::Any) => false,
|
|
(ProxyType::NonTransfer, _) => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl pallet_proxy::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type RuntimeCall = RuntimeCall;
|
|
type Currency = Balances;
|
|
type ProxyType = ProxyType;
|
|
type ProxyDepositBase = ProxyDepositBase;
|
|
type ProxyDepositFactor = ProxyDepositFactor;
|
|
type MaxProxies = MaxProxies;
|
|
type WeightInfo = weights::pallet_proxy::WeightInfo<Runtime>;
|
|
type MaxPending = MaxPending;
|
|
type CallHasher = BlakeTwo256;
|
|
type AnnouncementDepositBase = AnnouncementDepositBase;
|
|
type AnnouncementDepositFactor = AnnouncementDepositFactor;
|
|
}
|
|
|
|
impl parachains_origin::Config for Runtime {}
|
|
|
|
impl parachains_configuration::Config for Runtime {
|
|
type WeightInfo = weights::runtime_parachains_configuration::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl parachains_shared::Config for Runtime {
|
|
type DisabledValidators = Session;
|
|
}
|
|
|
|
impl parachains_session_info::Config for Runtime {
|
|
type ValidatorSet = Historical;
|
|
}
|
|
|
|
impl parachains_inclusion::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type DisputesHandler = ParasDisputes;
|
|
type RewardValidators = parachains_reward_points::RewardValidatorsWithEraPoints<Runtime>;
|
|
type MessageQueue = MessageQueue;
|
|
type WeightInfo = weights::runtime_parachains_inclusion::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
|
|
}
|
|
|
|
impl parachains_paras::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type WeightInfo = weights::runtime_parachains_paras::WeightInfo<Runtime>;
|
|
type UnsignedPriority = ParasUnsignedPriority;
|
|
type QueueFootprinter = ParaInclusion;
|
|
type NextSessionRotation = Babe;
|
|
type OnNewHead = ();
|
|
type AssignCoretime = ();
|
|
}
|
|
|
|
parameter_types! {
|
|
/// Amount of weight that can be spent per block to service messages.
|
|
///
|
|
/// # WARNING
|
|
///
|
|
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
|
|
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * BlockWeights::get().max_block;
|
|
pub const MessageQueueHeapSize: u32 = 128 * 1024;
|
|
pub const MessageQueueMaxStale: u32 = 48;
|
|
}
|
|
|
|
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
|
pub struct MessageProcessor;
|
|
impl ProcessMessage for MessageProcessor {
|
|
type Origin = AggregateMessageOrigin;
|
|
|
|
fn process_message(
|
|
message: &[u8],
|
|
origin: Self::Origin,
|
|
meter: &mut WeightMeter,
|
|
id: &mut [u8; 32],
|
|
) -> Result<bool, ProcessMessageError> {
|
|
let para = match origin {
|
|
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
|
};
|
|
xcm_builder::ProcessXcmMessage::<
|
|
Junction,
|
|
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
|
|
RuntimeCall,
|
|
>::process_message(message, Junction::Parachain(para.into()), meter, id)
|
|
}
|
|
}
|
|
|
|
impl pallet_message_queue::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Size = u32;
|
|
type HeapSize = MessageQueueHeapSize;
|
|
type MaxStale = MessageQueueMaxStale;
|
|
type ServiceWeight = MessageQueueServiceWeight;
|
|
#[cfg(not(feature = "runtime-benchmarks"))]
|
|
type MessageProcessor = MessageProcessor;
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
type MessageProcessor =
|
|
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
|
|
type QueueChangeHandler = ParaInclusion;
|
|
type QueuePausedQuery = ();
|
|
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl parachains_dmp::Config for Runtime {}
|
|
|
|
impl parachains_hrmp::Config for Runtime {
|
|
type RuntimeOrigin = RuntimeOrigin;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type ChannelManager = EnsureRoot<AccountId>;
|
|
type Currency = Balances;
|
|
type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo<Self>;
|
|
}
|
|
|
|
impl parachains_paras_inherent::Config for Runtime {
|
|
type WeightInfo = weights::runtime_parachains_paras_inherent::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl parachains_scheduler::Config for Runtime {
|
|
// If you change this, make sure the `Assignment` type of the new provider is binary compatible,
|
|
// otherwise provide a migration.
|
|
type AssignmentProvider = ParachainsAssignmentProvider;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const BrokerId: u32 = BROKER_ID;
|
|
}
|
|
|
|
impl parachains_assigner_parachains::Config for Runtime {}
|
|
|
|
impl parachains_initializer::Config for Runtime {
|
|
type Randomness = pallet_babe::RandomnessFromOneEpochAgo<Runtime>;
|
|
type ForceOrigin = EnsureRoot<AccountId>;
|
|
type WeightInfo = weights::runtime_parachains_initializer::WeightInfo<Runtime>;
|
|
type CoretimeOnNewSession = ();
|
|
}
|
|
|
|
impl paras_sudo_wrapper::Config for Runtime {}
|
|
|
|
parameter_types! {
|
|
pub const PermanentSlotLeasePeriodLength: u32 = 26;
|
|
pub const TemporarySlotLeasePeriodLength: u32 = 1;
|
|
pub const MaxTemporarySlotPerLeasePeriod: u32 = 5;
|
|
}
|
|
|
|
impl assigned_slots::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type AssignSlotOrigin = EnsureRoot<AccountId>;
|
|
type Leaser = Slots;
|
|
type PermanentSlotLeasePeriodLength = PermanentSlotLeasePeriodLength;
|
|
type TemporarySlotLeasePeriodLength = TemporarySlotLeasePeriodLength;
|
|
type MaxTemporarySlotPerLeasePeriod = MaxTemporarySlotPerLeasePeriod;
|
|
type WeightInfo = weights::runtime_common_assigned_slots::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl parachains_disputes::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type RewardValidators = parachains_reward_points::RewardValidatorsWithEraPoints<Runtime>;
|
|
type SlashingHandler = parachains_slashing::SlashValidatorsForDisputes<ParasSlashing>;
|
|
type WeightInfo = weights::runtime_parachains_disputes::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl parachains_slashing::Config for Runtime {
|
|
type KeyOwnerProofSystem = Historical;
|
|
type KeyOwnerProof =
|
|
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, ValidatorId)>>::Proof;
|
|
type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
|
|
KeyTypeId,
|
|
ValidatorId,
|
|
)>>::IdentificationTuple;
|
|
type HandleReports = parachains_slashing::SlashingReportHandler<
|
|
Self::KeyOwnerIdentification,
|
|
Offences,
|
|
ReportLongevity,
|
|
>;
|
|
type WeightInfo = weights::runtime_parachains_disputes_slashing::WeightInfo<Runtime>;
|
|
type BenchmarkingConfig = parachains_slashing::BenchConfig<300>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const ParaDeposit: Balance = 2000 * CENTS;
|
|
pub const RegistrarDataDepositPerByte: Balance = deposit(0, 1);
|
|
}
|
|
|
|
impl paras_registrar::Config for Runtime {
|
|
type RuntimeOrigin = RuntimeOrigin;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type OnSwap = (Crowdloan, Slots);
|
|
type ParaDeposit = ParaDeposit;
|
|
type DataDepositPerByte = RegistrarDataDepositPerByte;
|
|
type WeightInfo = weights::runtime_common_paras_registrar::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const LeasePeriod: BlockNumber = 28 * DAYS;
|
|
}
|
|
|
|
impl slots::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Currency = Balances;
|
|
type Registrar = Registrar;
|
|
type LeasePeriod = LeasePeriod;
|
|
type LeaseOffset = ();
|
|
type ForceOrigin = EitherOf<EnsureRoot<Self::AccountId>, LeaseAdmin>;
|
|
type WeightInfo = weights::runtime_common_slots::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const CrowdloanId: PalletId = PalletId(*b"py/cfund");
|
|
pub const SubmissionDeposit: Balance = 100 * 100 * CENTS;
|
|
pub const MinContribution: Balance = 100 * CENTS;
|
|
pub const RemoveKeysLimit: u32 = 500;
|
|
// Allow 32 bytes for an additional memo to a crowdloan.
|
|
pub const MaxMemoLength: u8 = 32;
|
|
}
|
|
|
|
impl crowdloan::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type PalletId = CrowdloanId;
|
|
type SubmissionDeposit = SubmissionDeposit;
|
|
type MinContribution = MinContribution;
|
|
type RemoveKeysLimit = RemoveKeysLimit;
|
|
type Registrar = Registrar;
|
|
type Auctioneer = Auctions;
|
|
type MaxMemoLength = MaxMemoLength;
|
|
type WeightInfo = weights::runtime_common_crowdloan::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
// The average auction is 7 days long, so this will be 70% for ending period.
|
|
// 5 Days = 72000 Blocks @ 6 sec per block
|
|
pub const EndingPeriod: BlockNumber = 5 * DAYS;
|
|
// ~ 1000 samples per day -> ~ 20 blocks per sample -> 2 minute samples
|
|
pub const SampleLength: BlockNumber = 2 * MINUTES;
|
|
}
|
|
|
|
impl auctions::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Leaser = Slots;
|
|
type Registrar = Registrar;
|
|
type EndingPeriod = EndingPeriod;
|
|
type SampleLength = SampleLength;
|
|
type Randomness = pallet_babe::RandomnessFromOneEpochAgo<Runtime>;
|
|
type InitiateOrigin = EitherOf<EnsureRoot<Self::AccountId>, AuctionAdmin>;
|
|
type WeightInfo = weights::runtime_common_auctions::WeightInfo<Runtime>;
|
|
}
|
|
|
|
impl identity_migrator::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type Reaper = EnsureSigned<AccountId>;
|
|
type ReapIdentityHandler = ToParachainIdentityReaper<Runtime, Self::AccountId>;
|
|
type WeightInfo = weights::runtime_common_identity_migrator::WeightInfo<Runtime>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const PoolsPalletId: PalletId = PalletId(*b"py/nopls");
|
|
pub const MaxPointsToBalance: u8 = 10;
|
|
}
|
|
|
|
impl pallet_nomination_pools::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type WeightInfo = weights::pallet_nomination_pools::WeightInfo<Self>;
|
|
type Currency = Balances;
|
|
type RuntimeFreezeReason = RuntimeFreezeReason;
|
|
type RewardCounter = FixedU128;
|
|
type BalanceToU256 = BalanceToU256;
|
|
type U256ToBalance = U256ToBalance;
|
|
type Staking = Staking;
|
|
type PostUnbondingPoolsWindow = ConstU32<4>;
|
|
type MaxMetadataLen = ConstU32<256>;
|
|
// we use the same number of allowed unlocking chunks as with staking.
|
|
type MaxUnbonding = <Self as pallet_staking::Config>::MaxUnlockingChunks;
|
|
type PalletId = PoolsPalletId;
|
|
type MaxPointsToBalance = MaxPointsToBalance;
|
|
}
|
|
|
|
impl pallet_root_testing::Config for Runtime {
|
|
type RuntimeEvent = RuntimeEvent;
|
|
}
|
|
|
|
parameter_types! {
|
|
// The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high)
|
|
pub const MigrationSignedDepositPerItem: Balance = 1 * CENTS;
|
|
pub const MigrationSignedDepositBase: Balance = 20 * CENTS * 100;
|
|
pub const MigrationMaxKeyLen: u32 = 512;
|
|
}
|
|
|
|
impl pallet_asset_rate::Config for Runtime {
|
|
type WeightInfo = weights::pallet_asset_rate::WeightInfo<Runtime>;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type CreateOrigin = EnsureRoot<AccountId>;
|
|
type RemoveOrigin = EnsureRoot<AccountId>;
|
|
type UpdateOrigin = EnsureRoot<AccountId>;
|
|
type Currency = Balances;
|
|
type AssetKind = <Runtime as pallet_treasury::Config>::AssetKind;
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments;
|
|
}
|
|
|
|
construct_runtime! {
|
|
pub enum Runtime
|
|
{
|
|
// Basic stuff; balances is uncallable initially.
|
|
System: frame_system = 0,
|
|
|
|
// Babe must be before session.
|
|
Babe: pallet_babe = 1,
|
|
|
|
Timestamp: pallet_timestamp = 2,
|
|
Indices: pallet_indices = 3,
|
|
Balances: pallet_balances = 4,
|
|
TransactionPayment: pallet_transaction_payment = 26,
|
|
|
|
// Consensus support.
|
|
// Authorship must be before session in order to note author in the correct session and era.
|
|
Authorship: pallet_authorship = 5,
|
|
Staking: pallet_staking = 6,
|
|
Offences: pallet_offences = 7,
|
|
Historical: session_historical = 27,
|
|
|
|
// BEEFY Bridges support.
|
|
Beefy: pallet_beefy = 200,
|
|
// MMR leaf construction must be before session in order to have leaf contents refer to
|
|
// block<N-1> consistently. see substrate issue #11797 for details.
|
|
Mmr: pallet_mmr = 201,
|
|
BeefyMmrLeaf: pallet_beefy_mmr = 202,
|
|
|
|
Session: pallet_session = 8,
|
|
Grandpa: pallet_grandpa = 10,
|
|
AuthorityDiscovery: pallet_authority_discovery = 12,
|
|
|
|
// Utility module.
|
|
Utility: pallet_utility = 16,
|
|
|
|
// Less simple identity module.
|
|
Identity: pallet_identity = 17,
|
|
|
|
// Social recovery module.
|
|
Recovery: pallet_recovery = 18,
|
|
|
|
// Vesting. Usable initially, but removed once all vesting is finished.
|
|
Vesting: pallet_vesting = 19,
|
|
|
|
// System scheduler.
|
|
Scheduler: pallet_scheduler = 20,
|
|
|
|
// Preimage registrar.
|
|
Preimage: pallet_preimage = 28,
|
|
|
|
// Sudo.
|
|
Sudo: pallet_sudo = 21,
|
|
|
|
// Proxy module. Late addition.
|
|
Proxy: pallet_proxy = 22,
|
|
|
|
// Multisig module. Late addition.
|
|
Multisig: pallet_multisig = 23,
|
|
|
|
// Election pallet. Only works with staking, but placed here to maintain indices.
|
|
ElectionProviderMultiPhase: pallet_election_provider_multi_phase = 24,
|
|
|
|
// Provides a semi-sorted list of nominators for staking.
|
|
VoterList: pallet_bags_list::<Instance1> = 25,
|
|
|
|
// Nomination pools for staking.
|
|
NominationPools: pallet_nomination_pools = 29,
|
|
|
|
// Fast unstake pallet: extension to staking.
|
|
FastUnstake: pallet_fast_unstake = 30,
|
|
|
|
// OpenGov
|
|
ConvictionVoting: pallet_conviction_voting = 31,
|
|
Referenda: pallet_referenda = 32,
|
|
Origins: pallet_custom_origins = 35,
|
|
Whitelist: pallet_whitelist = 36,
|
|
|
|
// Treasury
|
|
Treasury: pallet_treasury = 37,
|
|
|
|
// Parachains pallets. Start indices at 40 to leave room.
|
|
ParachainsOrigin: parachains_origin = 41,
|
|
Configuration: parachains_configuration = 42,
|
|
ParasShared: parachains_shared = 43,
|
|
ParaInclusion: parachains_inclusion = 44,
|
|
ParaInherent: parachains_paras_inherent = 45,
|
|
ParaScheduler: parachains_scheduler = 46,
|
|
Paras: parachains_paras = 47,
|
|
Initializer: parachains_initializer = 48,
|
|
Dmp: parachains_dmp = 49,
|
|
// RIP Ump 50
|
|
Hrmp: parachains_hrmp = 51,
|
|
ParaSessionInfo: parachains_session_info = 52,
|
|
ParasDisputes: parachains_disputes = 53,
|
|
ParasSlashing: parachains_slashing = 54,
|
|
ParachainsAssignmentProvider: parachains_assigner_parachains = 55,
|
|
|
|
// Parachain Onboarding Pallets. Start indices at 60 to leave room.
|
|
Registrar: paras_registrar = 60,
|
|
Slots: slots = 61,
|
|
ParasSudoWrapper: paras_sudo_wrapper = 62,
|
|
Auctions: auctions = 63,
|
|
Crowdloan: crowdloan = 64,
|
|
AssignedSlots: assigned_slots = 65,
|
|
|
|
// Pallet for sending XCM.
|
|
XcmPallet: pallet_xcm = 99,
|
|
|
|
// Generalized message queue
|
|
MessageQueue: pallet_message_queue = 100,
|
|
|
|
// Asset rate.
|
|
AssetRate: pallet_asset_rate = 101,
|
|
|
|
// Root testing pallet.
|
|
RootTesting: pallet_root_testing = 102,
|
|
|
|
// Pallet for migrating Identity to a parachain. To be removed post-migration.
|
|
IdentityMigrator: identity_migrator = 248,
|
|
}
|
|
}
|
|
|
|
/// The address format for describing accounts.
|
|
pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
|
|
/// Block header type as expected by this runtime.
|
|
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
|
/// Block type as expected by this runtime.
|
|
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
|
/// A Block signed with a Justification
|
|
pub type SignedBlock = generic::SignedBlock<Block>;
|
|
/// `BlockId` type as expected by this runtime.
|
|
pub type BlockId = generic::BlockId<Block>;
|
|
/// The `SignedExtension` to the basic transaction logic.
|
|
pub type SignedExtra = (
|
|
frame_system::CheckNonZeroSender<Runtime>,
|
|
frame_system::CheckSpecVersion<Runtime>,
|
|
frame_system::CheckTxVersion<Runtime>,
|
|
frame_system::CheckGenesis<Runtime>,
|
|
frame_system::CheckMortality<Runtime>,
|
|
frame_system::CheckNonce<Runtime>,
|
|
frame_system::CheckWeight<Runtime>,
|
|
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
|
);
|
|
|
|
pub struct NominationPoolsMigrationV4OldPallet;
|
|
impl Get<Perbill> for NominationPoolsMigrationV4OldPallet {
|
|
fn get() -> Perbill {
|
|
Perbill::from_percent(100)
|
|
}
|
|
}
|
|
|
|
/// All migrations that will run on the next runtime upgrade.
|
|
///
|
|
/// This contains the combined migrations of the last 10 releases. It allows to skip runtime
|
|
/// upgrades in case governance decides to do so. THE ORDER IS IMPORTANT.
|
|
pub type Migrations = migrations::Unreleased;
|
|
|
|
/// The runtime migrations per release.
|
|
#[allow(deprecated, missing_docs)]
|
|
pub mod migrations {
|
|
use super::*;
|
|
#[cfg(feature = "try-runtime")]
|
|
use sp_core::crypto::ByteArray;
|
|
|
|
parameter_types! {
|
|
pub const ImOnlinePalletName: &'static str = "ImOnline";
|
|
}
|
|
|
|
/// Upgrade Session keys to exclude `ImOnline` key.
|
|
/// When this is removed, should also remove `OldSessionKeys`.
|
|
pub struct UpgradeSessionKeys;
|
|
const UPGRADE_SESSION_KEYS_FROM_SPEC: u32 = 104000;
|
|
|
|
impl frame_support::traits::OnRuntimeUpgrade for UpgradeSessionKeys {
|
|
#[cfg(feature = "try-runtime")]
|
|
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::TryRuntimeError> {
|
|
if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC {
|
|
log::warn!(target: "runtime::session_keys", "Skipping session keys migration pre-upgrade check due to spec version (already applied?)");
|
|
return Ok(Vec::new())
|
|
}
|
|
|
|
log::info!(target: "runtime::session_keys", "Collecting pre-upgrade session keys state");
|
|
let key_ids = SessionKeys::key_ids();
|
|
frame_support::ensure!(
|
|
key_ids.into_iter().find(|&k| *k == sp_core::crypto::key_types::IM_ONLINE) == None,
|
|
"New session keys contain the ImOnline key that should have been removed",
|
|
);
|
|
let storage_key = pallet_session::QueuedKeys::<Runtime>::hashed_key();
|
|
let mut state: Vec<u8> = Vec::new();
|
|
frame_support::storage::unhashed::get::<Vec<(ValidatorId, OldSessionKeys)>>(
|
|
&storage_key,
|
|
)
|
|
.ok_or::<sp_runtime::TryRuntimeError>("Queued keys are not available".into())?
|
|
.into_iter()
|
|
.for_each(|(id, keys)| {
|
|
state.extend_from_slice(id.as_slice());
|
|
for key_id in key_ids {
|
|
state.extend_from_slice(keys.get_raw(*key_id));
|
|
}
|
|
});
|
|
frame_support::ensure!(state.len() > 0, "Queued keys are not empty before upgrade");
|
|
Ok(state)
|
|
}
|
|
|
|
fn on_runtime_upgrade() -> Weight {
|
|
if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC {
|
|
log::warn!("Skipping session keys upgrade: already applied");
|
|
return <Runtime as frame_system::Config>::DbWeight::get().reads(1)
|
|
}
|
|
log::info!("Upgrading session keys");
|
|
Session::upgrade_keys::<OldSessionKeys, _>(transform_session_keys);
|
|
Perbill::from_percent(50) * BlockWeights::get().max_block
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
fn post_upgrade(
|
|
old_state: sp_std::vec::Vec<u8>,
|
|
) -> Result<(), sp_runtime::TryRuntimeError> {
|
|
if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC {
|
|
log::warn!(target: "runtime::session_keys", "Skipping session keys migration post-upgrade check due to spec version (already applied?)");
|
|
return Ok(())
|
|
}
|
|
|
|
let key_ids = SessionKeys::key_ids();
|
|
let mut new_state: Vec<u8> = Vec::new();
|
|
pallet_session::QueuedKeys::<Runtime>::get().into_iter().for_each(|(id, keys)| {
|
|
new_state.extend_from_slice(id.as_slice());
|
|
for key_id in key_ids {
|
|
new_state.extend_from_slice(keys.get_raw(*key_id));
|
|
}
|
|
});
|
|
frame_support::ensure!(new_state.len() > 0, "Queued keys are not empty after upgrade");
|
|
frame_support::ensure!(
|
|
old_state == new_state,
|
|
"Pre-upgrade and post-upgrade keys do not match!"
|
|
);
|
|
log::info!(target: "runtime::session_keys", "Session keys migrated successfully");
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
// We don't have a limit in the Relay Chain.
|
|
const IDENTITY_MIGRATION_KEY_LIMIT: u64 = u64::MAX;
|
|
|
|
/// Unreleased migrations. Add new ones here:
|
|
pub type Unreleased = (
|
|
parachains_configuration::migration::v7::MigrateToV7<Runtime>,
|
|
pallet_staking::migrations::v14::MigrateToV14<Runtime>,
|
|
assigned_slots::migration::v1::MigrateToV1<Runtime>,
|
|
parachains_scheduler::migration::MigrateV1ToV2<Runtime>,
|
|
parachains_configuration::migration::v8::MigrateToV8<Runtime>,
|
|
parachains_configuration::migration::v9::MigrateToV9<Runtime>,
|
|
paras_registrar::migration::MigrateToV1<Runtime, ()>,
|
|
pallet_referenda::migration::v1::MigrateV0ToV1<Runtime, ()>,
|
|
pallet_grandpa::migrations::MigrateV4ToV5<Runtime>,
|
|
parachains_configuration::migration::v10::MigrateToV10<Runtime>,
|
|
pallet_nomination_pools::migration::versioned::V7ToV8<Runtime>,
|
|
UpgradeSessionKeys,
|
|
frame_support::migrations::RemovePallet<
|
|
ImOnlinePalletName,
|
|
<Runtime as frame_system::Config>::DbWeight,
|
|
>,
|
|
// Migrate Identity pallet for Usernames
|
|
pallet_identity::migration::versioned::V0ToV1<Runtime, IDENTITY_MIGRATION_KEY_LIMIT>,
|
|
parachains_configuration::migration::v11::MigrateToV11<Runtime>,
|
|
);
|
|
}
|
|
|
|
/// Unchecked extrinsic type as expected by this runtime.
|
|
pub type UncheckedExtrinsic =
|
|
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
|
|
/// Executive: handles dispatch to the various modules.
|
|
pub type Executive = frame_executive::Executive<
|
|
Runtime,
|
|
Block,
|
|
frame_system::ChainContext<Runtime>,
|
|
Runtime,
|
|
AllPalletsWithSystem,
|
|
Migrations,
|
|
>;
|
|
/// The payload being signed in transactions.
|
|
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
mod benches {
|
|
frame_benchmarking::define_benchmarks!(
|
|
// Polkadot
|
|
// NOTE: Make sure to prefix these with `runtime_common::` so
|
|
// the that path resolves correctly in the generated file.
|
|
[runtime_common::assigned_slots, AssignedSlots]
|
|
[runtime_common::auctions, Auctions]
|
|
[runtime_common::crowdloan, Crowdloan]
|
|
[runtime_common::identity_migrator, IdentityMigrator]
|
|
[runtime_common::paras_registrar, Registrar]
|
|
[runtime_common::slots, Slots]
|
|
[runtime_parachains::configuration, Configuration]
|
|
[runtime_parachains::disputes, ParasDisputes]
|
|
[runtime_parachains::disputes::slashing, ParasSlashing]
|
|
[runtime_parachains::hrmp, Hrmp]
|
|
[runtime_parachains::inclusion, ParaInclusion]
|
|
[runtime_parachains::initializer, Initializer]
|
|
[runtime_parachains::paras, Paras]
|
|
[runtime_parachains::paras_inherent, ParaInherent]
|
|
// Substrate
|
|
[pallet_bags_list, VoterList]
|
|
[pallet_balances, Balances]
|
|
[pallet_conviction_voting, ConvictionVoting]
|
|
[pallet_election_provider_multi_phase, ElectionProviderMultiPhase]
|
|
[frame_election_provider_support, ElectionProviderBench::<Runtime>]
|
|
[pallet_fast_unstake, FastUnstake]
|
|
[pallet_identity, Identity]
|
|
[pallet_indices, Indices]
|
|
[pallet_message_queue, MessageQueue]
|
|
[pallet_multisig, Multisig]
|
|
[pallet_nomination_pools, NominationPoolsBench::<Runtime>]
|
|
[pallet_offences, OffencesBench::<Runtime>]
|
|
[pallet_preimage, Preimage]
|
|
[pallet_proxy, Proxy]
|
|
[pallet_recovery, Recovery]
|
|
[pallet_referenda, Referenda]
|
|
[pallet_scheduler, Scheduler]
|
|
[pallet_session, SessionBench::<Runtime>]
|
|
[pallet_staking, Staking]
|
|
[pallet_sudo, Sudo]
|
|
[frame_system, SystemBench::<Runtime>]
|
|
[pallet_timestamp, Timestamp]
|
|
[pallet_treasury, Treasury]
|
|
[pallet_utility, Utility]
|
|
[pallet_vesting, Vesting]
|
|
[pallet_whitelist, Whitelist]
|
|
[pallet_asset_rate, AssetRate]
|
|
// XCM
|
|
[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
|
|
// NOTE: Make sure you point to the individual modules below.
|
|
[pallet_xcm_benchmarks::fungible, XcmBalances]
|
|
[pallet_xcm_benchmarks::generic, XcmGeneric]
|
|
);
|
|
}
|
|
|
|
sp_api::impl_runtime_apis! {
|
|
impl sp_api::Core<Block> for Runtime {
|
|
fn version() -> RuntimeVersion {
|
|
VERSION
|
|
}
|
|
|
|
fn execute_block(block: Block) {
|
|
Executive::execute_block(block);
|
|
}
|
|
|
|
fn initialize_block(header: &<Block as BlockT>::Header) {
|
|
Executive::initialize_block(header)
|
|
}
|
|
}
|
|
|
|
impl sp_api::Metadata<Block> for Runtime {
|
|
fn metadata() -> OpaqueMetadata {
|
|
OpaqueMetadata::new(Runtime::metadata().into())
|
|
}
|
|
|
|
fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
|
|
Runtime::metadata_at_version(version)
|
|
}
|
|
|
|
fn metadata_versions() -> sp_std::vec::Vec<u32> {
|
|
Runtime::metadata_versions()
|
|
}
|
|
}
|
|
|
|
impl block_builder_api::BlockBuilder<Block> for Runtime {
|
|
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
|
|
Executive::apply_extrinsic(extrinsic)
|
|
}
|
|
|
|
fn finalize_block() -> <Block as BlockT>::Header {
|
|
Executive::finalize_block()
|
|
}
|
|
|
|
fn inherent_extrinsics(data: inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
|
|
data.create_extrinsics()
|
|
}
|
|
|
|
fn check_inherents(
|
|
block: Block,
|
|
data: inherents::InherentData,
|
|
) -> inherents::CheckInherentsResult {
|
|
data.check_extrinsics(&block)
|
|
}
|
|
}
|
|
|
|
impl tx_pool_api::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
|
fn validate_transaction(
|
|
source: TransactionSource,
|
|
tx: <Block as BlockT>::Extrinsic,
|
|
block_hash: <Block as BlockT>::Hash,
|
|
) -> TransactionValidity {
|
|
Executive::validate_transaction(source, tx, block_hash)
|
|
}
|
|
}
|
|
|
|
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
|
|
fn offchain_worker(header: &<Block as BlockT>::Header) {
|
|
Executive::offchain_worker(header)
|
|
}
|
|
}
|
|
|
|
#[api_version(10)]
|
|
impl primitives::runtime_api::ParachainHost<Block> for Runtime {
|
|
fn validators() -> Vec<ValidatorId> {
|
|
parachains_runtime_api_impl::validators::<Runtime>()
|
|
}
|
|
|
|
fn validator_groups() -> (Vec<Vec<ValidatorIndex>>, GroupRotationInfo<BlockNumber>) {
|
|
parachains_runtime_api_impl::validator_groups::<Runtime>()
|
|
}
|
|
|
|
fn availability_cores() -> Vec<CoreState<Hash, BlockNumber>> {
|
|
parachains_runtime_api_impl::availability_cores::<Runtime>()
|
|
}
|
|
|
|
fn persisted_validation_data(para_id: ParaId, assumption: OccupiedCoreAssumption)
|
|
-> Option<PersistedValidationData<Hash, BlockNumber>> {
|
|
parachains_runtime_api_impl::persisted_validation_data::<Runtime>(para_id, assumption)
|
|
}
|
|
|
|
fn assumed_validation_data(
|
|
para_id: ParaId,
|
|
expected_persisted_validation_data_hash: Hash,
|
|
) -> Option<(PersistedValidationData<Hash, BlockNumber>, ValidationCodeHash)> {
|
|
parachains_runtime_api_impl::assumed_validation_data::<Runtime>(
|
|
para_id,
|
|
expected_persisted_validation_data_hash,
|
|
)
|
|
}
|
|
|
|
fn check_validation_outputs(
|
|
para_id: ParaId,
|
|
outputs: primitives::CandidateCommitments,
|
|
) -> bool {
|
|
parachains_runtime_api_impl::check_validation_outputs::<Runtime>(para_id, outputs)
|
|
}
|
|
|
|
fn session_index_for_child() -> SessionIndex {
|
|
parachains_runtime_api_impl::session_index_for_child::<Runtime>()
|
|
}
|
|
|
|
fn validation_code(para_id: ParaId, assumption: OccupiedCoreAssumption)
|
|
-> Option<ValidationCode> {
|
|
parachains_runtime_api_impl::validation_code::<Runtime>(para_id, assumption)
|
|
}
|
|
|
|
fn candidate_pending_availability(para_id: ParaId) -> Option<CommittedCandidateReceipt<Hash>> {
|
|
parachains_runtime_api_impl::candidate_pending_availability::<Runtime>(para_id)
|
|
}
|
|
|
|
fn candidate_events() -> Vec<CandidateEvent<Hash>> {
|
|
parachains_runtime_api_impl::candidate_events::<Runtime, _>(|ev| {
|
|
match ev {
|
|
RuntimeEvent::ParaInclusion(ev) => {
|
|
Some(ev)
|
|
}
|
|
_ => None,
|
|
}
|
|
})
|
|
}
|
|
|
|
fn session_info(index: SessionIndex) -> Option<SessionInfo> {
|
|
parachains_runtime_api_impl::session_info::<Runtime>(index)
|
|
}
|
|
|
|
fn session_executor_params(session_index: SessionIndex) -> Option<ExecutorParams> {
|
|
parachains_runtime_api_impl::session_executor_params::<Runtime>(session_index)
|
|
}
|
|
|
|
fn dmq_contents(recipient: ParaId) -> Vec<InboundDownwardMessage<BlockNumber>> {
|
|
parachains_runtime_api_impl::dmq_contents::<Runtime>(recipient)
|
|
}
|
|
|
|
fn inbound_hrmp_channels_contents(
|
|
recipient: ParaId
|
|
) -> BTreeMap<ParaId, Vec<InboundHrmpMessage<BlockNumber>>> {
|
|
parachains_runtime_api_impl::inbound_hrmp_channels_contents::<Runtime>(recipient)
|
|
}
|
|
|
|
fn validation_code_by_hash(hash: ValidationCodeHash) -> Option<ValidationCode> {
|
|
parachains_runtime_api_impl::validation_code_by_hash::<Runtime>(hash)
|
|
}
|
|
|
|
fn on_chain_votes() -> Option<ScrapedOnChainVotes<Hash>> {
|
|
parachains_runtime_api_impl::on_chain_votes::<Runtime>()
|
|
}
|
|
|
|
fn submit_pvf_check_statement(
|
|
stmt: PvfCheckStatement,
|
|
signature: ValidatorSignature,
|
|
) {
|
|
parachains_runtime_api_impl::submit_pvf_check_statement::<Runtime>(stmt, signature)
|
|
}
|
|
|
|
fn pvfs_require_precheck() -> Vec<ValidationCodeHash> {
|
|
parachains_runtime_api_impl::pvfs_require_precheck::<Runtime>()
|
|
}
|
|
|
|
fn validation_code_hash(para_id: ParaId, assumption: OccupiedCoreAssumption)
|
|
-> Option<ValidationCodeHash>
|
|
{
|
|
parachains_runtime_api_impl::validation_code_hash::<Runtime>(para_id, assumption)
|
|
}
|
|
|
|
fn disputes() -> Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)> {
|
|
parachains_runtime_api_impl::get_session_disputes::<Runtime>()
|
|
}
|
|
|
|
fn unapplied_slashes(
|
|
) -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)> {
|
|
parachains_runtime_api_impl::unapplied_slashes::<Runtime>()
|
|
}
|
|
|
|
fn key_ownership_proof(
|
|
validator_id: ValidatorId,
|
|
) -> Option<slashing::OpaqueKeyOwnershipProof> {
|
|
use parity_scale_codec::Encode;
|
|
|
|
Historical::prove((PARACHAIN_KEY_TYPE_ID, validator_id))
|
|
.map(|p| p.encode())
|
|
.map(slashing::OpaqueKeyOwnershipProof::new)
|
|
}
|
|
|
|
fn submit_report_dispute_lost(
|
|
dispute_proof: slashing::DisputeProof,
|
|
key_ownership_proof: slashing::OpaqueKeyOwnershipProof,
|
|
) -> Option<()> {
|
|
parachains_runtime_api_impl::submit_unsigned_slashing_report::<Runtime>(
|
|
dispute_proof,
|
|
key_ownership_proof,
|
|
)
|
|
}
|
|
|
|
fn minimum_backing_votes() -> u32 {
|
|
parachains_runtime_api_impl::minimum_backing_votes::<Runtime>()
|
|
}
|
|
|
|
fn para_backing_state(para_id: ParaId) -> Option<primitives::async_backing::BackingState> {
|
|
parachains_runtime_api_impl::backing_state::<Runtime>(para_id)
|
|
}
|
|
|
|
fn async_backing_params() -> primitives::AsyncBackingParams {
|
|
parachains_runtime_api_impl::async_backing_params::<Runtime>()
|
|
}
|
|
|
|
fn approval_voting_params() -> ApprovalVotingParams {
|
|
parachains_staging_runtime_api_impl::approval_voting_params::<Runtime>()
|
|
}
|
|
|
|
fn disabled_validators() -> Vec<ValidatorIndex> {
|
|
parachains_staging_runtime_api_impl::disabled_validators::<Runtime>()
|
|
}
|
|
|
|
fn node_features() -> NodeFeatures {
|
|
parachains_staging_runtime_api_impl::node_features::<Runtime>()
|
|
}
|
|
}
|
|
|
|
impl beefy_primitives::BeefyApi<Block, BeefyId> for Runtime {
|
|
fn beefy_genesis() -> Option<BlockNumber> {
|
|
Beefy::genesis_block()
|
|
}
|
|
|
|
fn validator_set() -> Option<beefy_primitives::ValidatorSet<BeefyId>> {
|
|
Beefy::validator_set()
|
|
}
|
|
|
|
fn submit_report_equivocation_unsigned_extrinsic(
|
|
equivocation_proof: beefy_primitives::EquivocationProof<
|
|
BlockNumber,
|
|
BeefyId,
|
|
BeefySignature,
|
|
>,
|
|
key_owner_proof: beefy_primitives::OpaqueKeyOwnershipProof,
|
|
) -> Option<()> {
|
|
let key_owner_proof = key_owner_proof.decode()?;
|
|
|
|
Beefy::submit_unsigned_equivocation_report(
|
|
equivocation_proof,
|
|
key_owner_proof,
|
|
)
|
|
}
|
|
|
|
fn generate_key_ownership_proof(
|
|
_set_id: beefy_primitives::ValidatorSetId,
|
|
authority_id: BeefyId,
|
|
) -> Option<beefy_primitives::OpaqueKeyOwnershipProof> {
|
|
use parity_scale_codec::Encode;
|
|
|
|
Historical::prove((beefy_primitives::KEY_TYPE, authority_id))
|
|
.map(|p| p.encode())
|
|
.map(beefy_primitives::OpaqueKeyOwnershipProof::new)
|
|
}
|
|
}
|
|
|
|
impl mmr::MmrApi<Block, Hash, BlockNumber> for Runtime {
|
|
fn mmr_root() -> Result<mmr::Hash, mmr::Error> {
|
|
Ok(Mmr::mmr_root())
|
|
}
|
|
|
|
fn mmr_leaf_count() -> Result<mmr::LeafIndex, mmr::Error> {
|
|
Ok(Mmr::mmr_leaves())
|
|
}
|
|
|
|
fn generate_proof(
|
|
block_numbers: Vec<BlockNumber>,
|
|
best_known_block_number: Option<BlockNumber>,
|
|
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
|
|
Mmr::generate_proof(block_numbers, best_known_block_number).map(
|
|
|(leaves, proof)| {
|
|
(
|
|
leaves
|
|
.into_iter()
|
|
.map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
|
|
.collect(),
|
|
proof,
|
|
)
|
|
},
|
|
)
|
|
}
|
|
|
|
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
|
|
-> Result<(), mmr::Error>
|
|
{
|
|
let leaves = leaves.into_iter().map(|leaf|
|
|
leaf.into_opaque_leaf()
|
|
.try_decode()
|
|
.ok_or(mmr::Error::Verify)).collect::<Result<Vec<mmr::Leaf>, mmr::Error>>()?;
|
|
Mmr::verify_leaves(leaves, proof)
|
|
}
|
|
|
|
fn verify_proof_stateless(
|
|
root: mmr::Hash,
|
|
leaves: Vec<mmr::EncodableOpaqueLeaf>,
|
|
proof: mmr::Proof<mmr::Hash>
|
|
) -> Result<(), mmr::Error> {
|
|
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
|
|
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
|
|
}
|
|
}
|
|
|
|
impl pallet_beefy_mmr::BeefyMmrApi<Block, Hash> for RuntimeApi {
|
|
fn authority_set_proof() -> beefy_primitives::mmr::BeefyAuthoritySet<Hash> {
|
|
BeefyMmrLeaf::authority_set_proof()
|
|
}
|
|
|
|
fn next_authority_set_proof() -> beefy_primitives::mmr::BeefyNextAuthoritySet<Hash> {
|
|
BeefyMmrLeaf::next_authority_set_proof()
|
|
}
|
|
}
|
|
|
|
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
|
fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
|
|
Grandpa::grandpa_authorities()
|
|
}
|
|
|
|
fn current_set_id() -> fg_primitives::SetId {
|
|
Grandpa::current_set_id()
|
|
}
|
|
|
|
fn submit_report_equivocation_unsigned_extrinsic(
|
|
equivocation_proof: fg_primitives::EquivocationProof<
|
|
<Block as BlockT>::Hash,
|
|
sp_runtime::traits::NumberFor<Block>,
|
|
>,
|
|
key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
|
|
) -> Option<()> {
|
|
let key_owner_proof = key_owner_proof.decode()?;
|
|
|
|
Grandpa::submit_unsigned_equivocation_report(
|
|
equivocation_proof,
|
|
key_owner_proof,
|
|
)
|
|
}
|
|
|
|
fn generate_key_ownership_proof(
|
|
_set_id: fg_primitives::SetId,
|
|
authority_id: fg_primitives::AuthorityId,
|
|
) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {
|
|
use parity_scale_codec::Encode;
|
|
|
|
Historical::prove((fg_primitives::KEY_TYPE, authority_id))
|
|
.map(|p| p.encode())
|
|
.map(fg_primitives::OpaqueKeyOwnershipProof::new)
|
|
}
|
|
}
|
|
|
|
impl babe_primitives::BabeApi<Block> for Runtime {
|
|
fn configuration() -> babe_primitives::BabeConfiguration {
|
|
let epoch_config = Babe::epoch_config().unwrap_or(BABE_GENESIS_EPOCH_CONFIG);
|
|
babe_primitives::BabeConfiguration {
|
|
slot_duration: Babe::slot_duration(),
|
|
epoch_length: EpochDuration::get(),
|
|
c: epoch_config.c,
|
|
authorities: Babe::authorities().to_vec(),
|
|
randomness: Babe::randomness(),
|
|
allowed_slots: epoch_config.allowed_slots,
|
|
}
|
|
}
|
|
|
|
fn current_epoch_start() -> babe_primitives::Slot {
|
|
Babe::current_epoch_start()
|
|
}
|
|
|
|
fn current_epoch() -> babe_primitives::Epoch {
|
|
Babe::current_epoch()
|
|
}
|
|
|
|
fn next_epoch() -> babe_primitives::Epoch {
|
|
Babe::next_epoch()
|
|
}
|
|
|
|
fn generate_key_ownership_proof(
|
|
_slot: babe_primitives::Slot,
|
|
authority_id: babe_primitives::AuthorityId,
|
|
) -> Option<babe_primitives::OpaqueKeyOwnershipProof> {
|
|
use parity_scale_codec::Encode;
|
|
|
|
Historical::prove((babe_primitives::KEY_TYPE, authority_id))
|
|
.map(|p| p.encode())
|
|
.map(babe_primitives::OpaqueKeyOwnershipProof::new)
|
|
}
|
|
|
|
fn submit_report_equivocation_unsigned_extrinsic(
|
|
equivocation_proof: babe_primitives::EquivocationProof<<Block as BlockT>::Header>,
|
|
key_owner_proof: babe_primitives::OpaqueKeyOwnershipProof,
|
|
) -> Option<()> {
|
|
let key_owner_proof = key_owner_proof.decode()?;
|
|
|
|
Babe::submit_unsigned_equivocation_report(
|
|
equivocation_proof,
|
|
key_owner_proof,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl authority_discovery_primitives::AuthorityDiscoveryApi<Block> for Runtime {
|
|
fn authorities() -> Vec<AuthorityDiscoveryId> {
|
|
parachains_runtime_api_impl::relevant_authority_ids::<Runtime>()
|
|
}
|
|
}
|
|
|
|
impl sp_session::SessionKeys<Block> for Runtime {
|
|
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
|
SessionKeys::generate(seed)
|
|
}
|
|
|
|
fn decode_session_keys(
|
|
encoded: Vec<u8>,
|
|
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
|
|
SessionKeys::decode_into_raw_public_keys(&encoded)
|
|
}
|
|
}
|
|
|
|
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
|
|
fn account_nonce(account: AccountId) -> Nonce {
|
|
System::account_nonce(account)
|
|
}
|
|
}
|
|
|
|
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
|
|
Block,
|
|
Balance,
|
|
> for Runtime {
|
|
fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
|
|
TransactionPayment::query_info(uxt, len)
|
|
}
|
|
fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {
|
|
TransactionPayment::query_fee_details(uxt, len)
|
|
}
|
|
fn query_weight_to_fee(weight: Weight) -> Balance {
|
|
TransactionPayment::weight_to_fee(weight)
|
|
}
|
|
fn query_length_to_fee(length: u32) -> Balance {
|
|
TransactionPayment::length_to_fee(length)
|
|
}
|
|
}
|
|
|
|
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
|
|
for Runtime
|
|
{
|
|
fn query_call_info(call: RuntimeCall, len: u32) -> RuntimeDispatchInfo<Balance> {
|
|
TransactionPayment::query_call_info(call, len)
|
|
}
|
|
fn query_call_fee_details(call: RuntimeCall, len: u32) -> FeeDetails<Balance> {
|
|
TransactionPayment::query_call_fee_details(call, len)
|
|
}
|
|
fn query_weight_to_fee(weight: Weight) -> Balance {
|
|
TransactionPayment::weight_to_fee(weight)
|
|
}
|
|
fn query_length_to_fee(length: u32) -> Balance {
|
|
TransactionPayment::length_to_fee(length)
|
|
}
|
|
}
|
|
|
|
impl pallet_nomination_pools_runtime_api::NominationPoolsApi<
|
|
Block,
|
|
AccountId,
|
|
Balance,
|
|
> for Runtime {
|
|
fn pending_rewards(member: AccountId) -> Balance {
|
|
NominationPools::api_pending_rewards(member).unwrap_or_default()
|
|
}
|
|
|
|
fn points_to_balance(pool_id: pallet_nomination_pools::PoolId, points: Balance) -> Balance {
|
|
NominationPools::api_points_to_balance(pool_id, points)
|
|
}
|
|
|
|
fn balance_to_points(pool_id: pallet_nomination_pools::PoolId, new_funds: Balance) -> Balance {
|
|
NominationPools::api_balance_to_points(pool_id, new_funds)
|
|
}
|
|
}
|
|
|
|
impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime {
|
|
fn nominations_quota(balance: Balance) -> u32 {
|
|
Staking::api_nominations_quota(balance)
|
|
}
|
|
|
|
fn eras_stakers_page_count(era: sp_staking::EraIndex, account: AccountId) -> sp_staking::Page {
|
|
Staking::api_eras_stakers_page_count(era, account)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
impl frame_try_runtime::TryRuntime<Block> for Runtime {
|
|
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
|
|
log::info!("try-runtime::on_runtime_upgrade westend.");
|
|
let weight = Executive::try_runtime_upgrade(checks).unwrap();
|
|
(weight, BlockWeights::get().max_block)
|
|
}
|
|
|
|
fn execute_block(
|
|
block: Block,
|
|
state_root_check: bool,
|
|
signature_check: bool,
|
|
select: frame_try_runtime::TryStateSelect,
|
|
) -> Weight {
|
|
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
|
|
// have a backtrace here.
|
|
Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
impl frame_benchmarking::Benchmark<Block> for Runtime {
|
|
fn benchmark_metadata(extra: bool) -> (
|
|
Vec<frame_benchmarking::BenchmarkList>,
|
|
Vec<frame_support::traits::StorageInfo>,
|
|
) {
|
|
use frame_benchmarking::{Benchmarking, BenchmarkList};
|
|
use frame_support::traits::StorageInfoTrait;
|
|
|
|
use pallet_session_benchmarking::Pallet as SessionBench;
|
|
use pallet_offences_benchmarking::Pallet as OffencesBench;
|
|
use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench;
|
|
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
|
|
use frame_system_benchmarking::Pallet as SystemBench;
|
|
use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench;
|
|
|
|
type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
|
|
type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
|
|
|
|
let mut list = Vec::<BenchmarkList>::new();
|
|
list_benchmarks!(list, extra);
|
|
|
|
let storage_info = AllPalletsWithSystem::storage_info();
|
|
return (list, storage_info)
|
|
}
|
|
|
|
fn dispatch_benchmark(
|
|
config: frame_benchmarking::BenchmarkConfig,
|
|
) -> Result<
|
|
Vec<frame_benchmarking::BenchmarkBatch>,
|
|
sp_runtime::RuntimeString,
|
|
> {
|
|
use frame_support::traits::WhitelistedStorageKeys;
|
|
use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError};
|
|
use sp_storage::TrackedStorageKey;
|
|
// Trying to add benchmarks directly to some pallets caused cyclic dependency issues.
|
|
// To get around that, we separated the benchmarks into its own crate.
|
|
use pallet_session_benchmarking::Pallet as SessionBench;
|
|
use pallet_offences_benchmarking::Pallet as OffencesBench;
|
|
use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench;
|
|
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
|
|
use frame_system_benchmarking::Pallet as SystemBench;
|
|
use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench;
|
|
|
|
impl pallet_session_benchmarking::Config for Runtime {}
|
|
impl pallet_offences_benchmarking::Config for Runtime {}
|
|
impl pallet_election_provider_support_benchmarking::Config for Runtime {}
|
|
impl pallet_xcm::benchmarking::Config for Runtime {
|
|
fn reachable_dest() -> Option<Location> {
|
|
Some(crate::xcm_config::AssetHub::get())
|
|
}
|
|
|
|
fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
|
|
// Relay/native token can be teleported to/from AH.
|
|
Some((
|
|
Asset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: AssetId(Here.into()) },
|
|
crate::xcm_config::AssetHub::get(),
|
|
))
|
|
}
|
|
|
|
fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
|
|
// Relay can reserve transfer native token to some random parachain.
|
|
Some((
|
|
Asset {
|
|
fun: Fungible(EXISTENTIAL_DEPOSIT),
|
|
id: AssetId(Here.into())
|
|
},
|
|
crate::Junction::Parachain(43211234).into(),
|
|
))
|
|
}
|
|
|
|
fn set_up_complex_asset_transfer(
|
|
) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
|
|
// Relay supports only native token, either reserve transfer it to non-system parachains,
|
|
// or teleport it to system parachain. Use the teleport case for benchmarking as it's
|
|
// slightly heavier.
|
|
|
|
// Relay/native token can be teleported to/from AH.
|
|
let native_location = Here.into();
|
|
let dest = crate::xcm_config::AssetHub::get();
|
|
pallet_xcm::benchmarking::helpers::native_teleport_as_asset_transfer::<Runtime>(
|
|
native_location,
|
|
dest
|
|
)
|
|
}
|
|
}
|
|
impl frame_system_benchmarking::Config for Runtime {}
|
|
impl pallet_nomination_pools_benchmarking::Config for Runtime {}
|
|
impl runtime_parachains::disputes::slashing::benchmarking::Config for Runtime {}
|
|
|
|
use xcm::latest::{
|
|
AssetId, Fungibility::*, InteriorLocation, Junction, Junctions::*,
|
|
Asset, Assets, Location, NetworkId, Response,
|
|
};
|
|
use xcm_config::{AssetHub, TokenLocation};
|
|
|
|
parameter_types! {
|
|
pub ExistentialDepositAsset: Option<Asset> = Some((
|
|
TokenLocation::get(),
|
|
ExistentialDeposit::get()
|
|
).into());
|
|
pub ToParachain: ParaId = westend_runtime_constants::system_parachain::ASSET_HUB_ID.into();
|
|
}
|
|
|
|
impl pallet_xcm_benchmarks::Config for Runtime {
|
|
type XcmConfig = xcm_config::XcmConfig;
|
|
type AccountIdConverter = xcm_config::LocationConverter;
|
|
type DeliveryHelper = runtime_common::xcm_sender::ToParachainDeliveryHelper<
|
|
xcm_config::XcmConfig,
|
|
ExistentialDepositAsset,
|
|
xcm_config::PriceForChildParachainDelivery,
|
|
ToParachain,
|
|
(),
|
|
>;
|
|
fn valid_destination() -> Result<Location, BenchmarkError> {
|
|
Ok(AssetHub::get())
|
|
}
|
|
fn worst_case_holding(_depositable_count: u32) -> Assets {
|
|
// Westend only knows about WND.
|
|
vec![Asset{
|
|
id: AssetId(TokenLocation::get()),
|
|
fun: Fungible(1_000_000 * UNITS),
|
|
}].into()
|
|
}
|
|
}
|
|
|
|
parameter_types! {
|
|
pub TrustedTeleporter: Option<(Location, Asset)> = Some((
|
|
AssetHub::get(),
|
|
Asset { fun: Fungible(1 * UNITS), id: AssetId(TokenLocation::get()) },
|
|
));
|
|
pub const TrustedReserve: Option<(Location, Asset)> = None;
|
|
}
|
|
|
|
impl pallet_xcm_benchmarks::fungible::Config for Runtime {
|
|
type TransactAsset = Balances;
|
|
|
|
type CheckedAccount = xcm_config::LocalCheckAccount;
|
|
type TrustedTeleporter = TrustedTeleporter;
|
|
type TrustedReserve = TrustedReserve;
|
|
|
|
fn get_asset() -> Asset {
|
|
Asset {
|
|
id: AssetId(TokenLocation::get()),
|
|
fun: Fungible(1 * UNITS),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl pallet_xcm_benchmarks::generic::Config for Runtime {
|
|
type TransactAsset = Balances;
|
|
type RuntimeCall = RuntimeCall;
|
|
|
|
fn worst_case_response() -> (u64, Response) {
|
|
(0u64, Response::Version(Default::default()))
|
|
}
|
|
|
|
fn worst_case_asset_exchange() -> Result<(Assets, Assets), BenchmarkError> {
|
|
// Westend doesn't support asset exchanges
|
|
Err(BenchmarkError::Skip)
|
|
}
|
|
|
|
fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
|
|
// The XCM executor of Westend doesn't have a configured `UniversalAliases`
|
|
Err(BenchmarkError::Skip)
|
|
}
|
|
|
|
fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> {
|
|
Ok((AssetHub::get(), frame_system::Call::remark_with_event { remark: vec![] }.into()))
|
|
}
|
|
|
|
fn subscribe_origin() -> Result<Location, BenchmarkError> {
|
|
Ok(AssetHub::get())
|
|
}
|
|
|
|
fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError> {
|
|
let origin = AssetHub::get();
|
|
let assets: Assets = (AssetId(TokenLocation::get()), 1_000 * UNITS).into();
|
|
let ticket = Location { parents: 0, interior: Here };
|
|
Ok((origin, ticket, assets))
|
|
}
|
|
|
|
fn fee_asset() -> Result<Asset, BenchmarkError> {
|
|
Ok(Asset {
|
|
id: AssetId(TokenLocation::get()),
|
|
fun: Fungible(1_000_000 * UNITS),
|
|
})
|
|
}
|
|
|
|
fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
|
|
// Westend doesn't support asset locking
|
|
Err(BenchmarkError::Skip)
|
|
}
|
|
|
|
fn export_message_origin_and_destination(
|
|
) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
|
|
// Westend doesn't support exporting messages
|
|
Err(BenchmarkError::Skip)
|
|
}
|
|
|
|
fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
|
|
// The XCM executor of Westend doesn't have a configured `Aliasers`
|
|
Err(BenchmarkError::Skip)
|
|
}
|
|
}
|
|
|
|
type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
|
|
type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
|
|
|
|
let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
|
|
|
|
let mut batches = Vec::<BenchmarkBatch>::new();
|
|
let params = (&config, &whitelist);
|
|
|
|
add_benchmarks!(params, batches);
|
|
|
|
Ok(batches)
|
|
}
|
|
}
|
|
|
|
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
|
|
fn create_default_config() -> Vec<u8> {
|
|
create_default_config::<RuntimeGenesisConfig>()
|
|
}
|
|
|
|
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
|
|
build_config::<RuntimeGenesisConfig>(config)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(all(test, feature = "try-runtime"))]
|
|
mod remote_tests {
|
|
use super::*;
|
|
use frame_try_runtime::{runtime_decl_for_try_runtime::TryRuntime, UpgradeCheckSelect};
|
|
use remote_externalities::{
|
|
Builder, Mode, OfflineConfig, OnlineConfig, SnapshotConfig, Transport,
|
|
};
|
|
use std::env::var;
|
|
|
|
#[tokio::test]
|
|
async fn run_migrations() {
|
|
if var("RUN_MIGRATION_TESTS").is_err() {
|
|
return
|
|
}
|
|
|
|
sp_tracing::try_init_simple();
|
|
let transport: Transport =
|
|
var("WS").unwrap_or("wss://westend-rpc.polkadot.io:443".to_string()).into();
|
|
let maybe_state_snapshot: Option<SnapshotConfig> = var("SNAP").map(|s| s.into()).ok();
|
|
let mut ext = Builder::<Block>::default()
|
|
.mode(if let Some(state_snapshot) = maybe_state_snapshot {
|
|
Mode::OfflineOrElseOnline(
|
|
OfflineConfig { state_snapshot: state_snapshot.clone() },
|
|
OnlineConfig {
|
|
transport,
|
|
state_snapshot: Some(state_snapshot),
|
|
..Default::default()
|
|
},
|
|
)
|
|
} else {
|
|
Mode::Online(OnlineConfig { transport, ..Default::default() })
|
|
})
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
ext.execute_with(|| Runtime::on_runtime_upgrade(UpgradeCheckSelect::PreAndPost));
|
|
}
|
|
}
|
|
|
|
mod clean_state_migration {
|
|
use super::Runtime;
|
|
#[cfg(feature = "try-runtime")]
|
|
use super::Vec;
|
|
use frame_support::{pallet_prelude::*, storage_alias, traits::OnRuntimeUpgrade};
|
|
use pallet_state_trie_migration::MigrationLimits;
|
|
|
|
#[storage_alias]
|
|
type AutoLimits = StorageValue<StateTrieMigration, Option<MigrationLimits>, ValueQuery>;
|
|
|
|
// Actual type of value is `MigrationTask<T>`, putting a dummy
|
|
// one to avoid the trait constraint on T.
|
|
// Since we only use `kill` it is fine.
|
|
#[storage_alias]
|
|
type MigrationProcess = StorageValue<StateTrieMigration, u32, ValueQuery>;
|
|
|
|
#[storage_alias]
|
|
type SignedMigrationMaxLimits = StorageValue<StateTrieMigration, MigrationLimits, OptionQuery>;
|
|
|
|
/// Initialize an automatic migration process.
|
|
pub struct CleanMigrate;
|
|
|
|
impl OnRuntimeUpgrade for CleanMigrate {
|
|
#[cfg(feature = "try-runtime")]
|
|
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
|
Ok(Default::default())
|
|
}
|
|
|
|
fn on_runtime_upgrade() -> frame_support::weights::Weight {
|
|
MigrationProcess::kill();
|
|
AutoLimits::kill();
|
|
SignedMigrationMaxLimits::kill();
|
|
<Runtime as frame_system::Config>::DbWeight::get().writes(3)
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
|
frame_support::ensure!(
|
|
!AutoLimits::exists() && !SignedMigrationMaxLimits::exists(),
|
|
"State migration clean.",
|
|
);
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|