Newer
Older
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! The Substrate runtime. This can be compiled with `#[no_std]`, ready for Wasm.
Alexandru Vasile
committed
// `construct_runtime!` does a lot of recursion and requires us to increase the limits.
#![recursion_limit = "1024"]
use codec::{Decode, Encode, MaxEncodedLen};
use frame_election_provider_support::{
bounds::{ElectionBounds, ElectionBoundsBuilder},
Gonçalo Pestana
committed
onchain, BalancingConfig, ElectionDataProvider, SequentialPhragmen, VoteWeight,
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
instances::{Instance1, Instance2},
ord_parameter_types,
pallet_prelude::Get,
parameter_types,
fungible::{
Balanced, Credit, HoldConsideration, ItemOf, NativeFromLeft, NativeOrWithId, UnionOf,
},
tokens::{
imbalance::ResolveAssetTo, nonfungibles_v2::Inspect, pay::PayAssetFromAccount,
GetSalary, PayFromAccount,
},
AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Contains, Currency,
EitherOfDiverse, EqualPrivilegeOnly, Imbalance, InsideBoth, InstanceFilter,
KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing, OnUnbalanced,
WithdrawReasons,
weights::{
constants::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND,
},
ConstantMultiplier, IdentityFee, Weight,
BoundedVec, PalletId,
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureRootWithSuccess, EnsureSigned, EnsureSignedBy, EnsureWithSuccess,
};
pub use node_primitives::{AccountId, Signature};
use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Moment, Nonce};
use pallet_asset_conversion::{Ascending, Chain, WithFirstAsset};
use pallet_broker::{CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600};
Gonçalo Pestana
committed
use pallet_election_provider_multi_phase::{GeometricDepositBase, SolutionAccuracyOf};
use pallet_identity::legacy::IdentityInfo;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use pallet_session::historical as pallet_session_historical;
pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment};
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_tx_pause::RuntimeCallNameOf;
use sp_api::impl_runtime_apis;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_beefy::{
ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
mmr::MmrLeafVersion,
};
use sp_consensus_grandpa::AuthorityId as GrandpaId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_inherents::{CheckInherentsResult, InherentData};
create_runtime_str,
curve::PiecewiseLinear,
generic, impl_opaque_keys,
traits::{
self, AccountIdConversion, BlakeTwo256, Block as BlockT, Bounded, ConvertInto, NumberFor,
OpaqueKeys, SaturatedConversion, StaticLookup,
},
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perbill, Percent, Permill, Perquintill,
Bastian Köcher
committed
};
#[cfg(any(feature = "std", test))]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
pub use frame_system::Call as SystemCall;
#[cfg(any(feature = "std", test))]
pub use pallet_balances::Call as BalancesCall;
#[cfg(any(feature = "std", test))]
pub use pallet_staking::StakerStatus;
#[cfg(any(feature = "std", test))]
pub use pallet_sudo::Call as SudoCall;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
/// Implementations of some helper traits passed into runtime modules as associated types.
#[cfg(not(feature = "runtime-benchmarks"))]
use impls::AllianceIdentityVerifier;
use impls::{AllianceProposalProvider, Author, CreditToBlockAuthor};
/// Constant values used within the runtime.
pub mod constants;
use constants::{currency::*, time::*};
/// Generated voter bag information.
mod voter_bags;
/// Runtime API definition for assets.
pub mod assets_api;
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
/// Max size for serialized extrinsic params for this testing runtime.
/// This is a quite arbitrary but empirically battle tested value.
#[cfg(test)]
pub const CALL_PARAMS_MAX_SIZE: usize = 244;
/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics.
#[cfg(feature = "std")]
pub fn wasm_binary_unwrap() -> &'static [u8] {
"Development wasm binary is not available. This means the client is built with \
`SKIP_WASM_BUILD` flag and it is only usable for production chains. Please rebuild with \
the flag disabled.",
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"),
// Per convention: if the runtime behavior changes, increment spec_version
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 268,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
state_version: 1,
/// The BABE epoch configuration at genesis.
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
sp_consensus_babe::BabeEpochConfiguration {
c: PRIMARY_PROBABILITY,
allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots,
};
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
pub struct DealWithFees;
impl OnUnbalanced<NegativeImbalance> for DealWithFees {
fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
if let Some(fees) = fees_then_tips.next() {
// for fees, 80% to treasury, 20% to author
let mut split = fees.ration(80, 20);
if let Some(tips) = fees_then_tips.next() {
// for tips, if any, 80% to treasury, 20% to author (though this can be anything)
tips.ration_merge_into(80, 20, &mut split);
}
Treasury::on_unbalanced(split.0);
Author::on_unbalanced(split.1);
}
}
}
/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
/// This is used to limit the maximal weight of a single extrinsic.
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
/// by Operational extrinsics.
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size.
const MAXIMUM_BLOCK_WEIGHT: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
pub const BlockHashCount: BlockNumber = 2400;
pub const Version: RuntimeVersion = VERSION;
pub RuntimeBlockLength: BlockLength =
BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
.base_block(BlockExecutionWeight::get())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = ExtrinsicBaseWeight::get();
})
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
// Operational transactions have some extra reserved space, so that they
// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
weights.reserved = Some(
MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
);
})
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic();
pub MaxCollectivesProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
}
const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct());
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/// Calls that can bypass the safe-mode pallet.
pub struct SafeModeWhitelistedCalls;
impl Contains<RuntimeCall> for SafeModeWhitelistedCalls {
fn contains(call: &RuntimeCall) -> bool {
match call {
RuntimeCall::System(_) | RuntimeCall::SafeMode(_) | RuntimeCall::TxPause(_) => true,
_ => false,
}
}
}
/// Calls that cannot be paused by the tx-pause pallet.
pub struct TxPauseWhitelistedCalls;
/// Whitelist `Balances::transfer_keep_alive`, all others are pauseable.
impl Contains<RuntimeCallNameOf<Runtime>> for TxPauseWhitelistedCalls {
fn contains(full_name: &RuntimeCallNameOf<Runtime>) -> bool {
match (full_name.0.as_slice(), full_name.1.as_slice()) {
(b"Balances", b"transfer_keep_alive") => true,
_ => false,
}
}
}
impl pallet_tx_pause::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type PauseOrigin = EnsureRoot<AccountId>;
type UnpauseOrigin = EnsureRoot<AccountId>;
type WhitelistedCalls = TxPauseWhitelistedCalls;
type MaxNameLen = ConstU32<256>;
type WeightInfo = pallet_tx_pause::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const EnterDuration: BlockNumber = 4 * HOURS;
pub const EnterDepositAmount: Balance = 2_000_000 * DOLLARS;
pub const ExtendDuration: BlockNumber = 2 * HOURS;
pub const ExtendDepositAmount: Balance = 1_000_000 * DOLLARS;
pub const ReleaseDelay: u32 = 2 * DAYS;
}
impl pallet_safe_mode::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type RuntimeHoldReason = RuntimeHoldReason;
type WhitelistedCalls = SafeModeWhitelistedCalls;
type EnterDuration = EnterDuration;
type EnterDepositAmount = EnterDepositAmount;
type ExtendDuration = ExtendDuration;
type ExtendDepositAmount = ExtendDepositAmount;
type ForceEnterOrigin = EnsureRootWithSuccess<AccountId, ConstU32<9>>;
type ForceExtendOrigin = EnsureRootWithSuccess<AccountId, ConstU32<11>>;
type ForceExitOrigin = EnsureRoot<AccountId>;
type ForceDepositOrigin = EnsureRoot<AccountId>;
type ReleaseDelay = ReleaseDelay;
type Notify = ();
type WeightInfo = pallet_safe_mode::weights::SubstrateWeight<Runtime>;
}
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Runtime {
type BaseCallFilter = InsideBoth<SafeMode, TxPause>;
type BlockWeights = RuntimeBlockWeights;
type BlockLength = RuntimeBlockLength;
type DbWeight = RocksDbWeight;
type Block = Block;
type BlockHashCount = BlockHashCount;
type Version = Version;
type AccountData = pallet_balances::AccountData<Balance>;
type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
type SS58Prefix = ConstU16<42>;
type MaxConsumers = ConstU32<16>;
impl pallet_insecure_randomness_collective_flip::Config for Runtime {}
impl pallet_example_tasks::Config for Runtime {
type RuntimeTask = RuntimeTask;
type WeightInfo = pallet_example_tasks::weights::SubstrateWeight<Runtime>;
}
impl pallet_utility::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = pallet_utility::weights::SubstrateWeight<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);
impl pallet_multisig::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = ConstU32<100>;
type WeightInfo = pallet_multisig::weights::SubstrateWeight<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 AnnouncementDepositBase: Balance = deposit(1, 8);
pub const AnnouncementDepositFactor: Balance = deposit(0, 66);
}
/// The type used to represent the kinds of proxying allowed.
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Encode,
Decode,
RuntimeDebug,
MaxEncodedLen,
scale_info::TypeInfo,
pub enum ProxyType {
Any,
NonTransfer,
Governance,
Staking,
}
impl Default for ProxyType {
fn default() -> Self {
Self::Any
}
}
impl InstanceFilter<RuntimeCall> for ProxyType {
fn filter(&self, c: &RuntimeCall) -> bool {
ProxyType::NonTransfer => !matches!(
c,
RuntimeCall::Balances(..) |
RuntimeCall::Assets(..) |
RuntimeCall::Uniques(..) |
RuntimeCall::Vesting(pallet_vesting::Call::vested_transfer { .. }) |
RuntimeCall::Indices(pallet_indices::Call::transfer { .. })
ProxyType::Governance => matches!(
c,
RuntimeCall::Democracy(..) |
RuntimeCall::Council(..) |
RuntimeCall::Society(..) |
RuntimeCall::TechnicalCommittee(..) |
RuntimeCall::Elections(..) |
RuntimeCall::Treasury(..)
ProxyType::Staking => {
matches!(c, RuntimeCall::Staking(..) | RuntimeCall::FastUnstake(..))
},
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 = ConstU32<32>;
type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
type MaxPending = ConstU32<32>;
type CallHasher = BlakeTwo256;
type AnnouncementDepositBase = AnnouncementDepositBase;
type AnnouncementDepositFactor = AnnouncementDepositFactor;
parameter_types! {
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) *
RuntimeBlockWeights::get().max_block;
}
impl pallet_scheduler::Config for Runtime {
type PalletsOrigin = OriginCaller;
type MaximumWeight = MaximumSchedulerWeight;
type ScheduleOrigin = EnsureRoot<AccountId>;
#[cfg(feature = "runtime-benchmarks")]
#[cfg(not(feature = "runtime-benchmarks"))]
type MaxScheduledPerBlock = ConstU32<50>;
type WeightInfo = pallet_scheduler::weights::SubstrateWeight<Runtime>;
type OriginPrivilegeCmp = EqualPrivilegeOnly;
impl pallet_glutton::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AdminOrigin = EnsureRoot<AccountId>;
type WeightInfo = pallet_glutton::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const PreimageBaseDeposit: Balance = 1 * DOLLARS;
// One cent: $10,000 / MB
pub const PreimageByteDeposit: Balance = 1 * CENTS;
pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
}
impl pallet_preimage::Config for Runtime {
type WeightInfo = pallet_preimage::weights::SubstrateWeight<Runtime>;
type Currency = Balances;
type ManagerOrigin = EnsureRoot<AccountId>;
type Consideration = HoldConsideration<
AccountId,
Balances,
PreimageHoldReason,
LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
>;
}
// NOTE: Currently it is not possible to change the epoch duration after the chain has started.
// Attempting to do so will brick block production.
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
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;
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
type DisabledValidators = Session;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = MaxNominators;
type KeyOwnerProof =
<Historical as KeyOwnerProofSystem<(KeyTypeId, pallet_babe::AuthorityId)>>::Proof;
type EquivocationReportSystem =
pallet_babe::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
parameter_types! {
pub const IndexDeposit: Balance = 1 * DOLLARS;
}
impl pallet_indices::Config for Runtime {
type Currency = Balances;
type Deposit = IndexDeposit;
type WeightInfo = pallet_indices::weights::SubstrateWeight<Runtime>;
parameter_types! {
pub const ExistentialDeposit: Balance = 1 * DOLLARS;
// For weight estimation, we assume that the most locks on an individual account will be 50.
// This number may need to be adjusted in the future if this assumption no longer holds true.
pub const MaxLocks: u32 = 50;
impl pallet_balances::Config for Runtime {
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
type Balance = Balance;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = frame_system::Pallet<Runtime>;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = ConstU32<1>;
type MaxHolds = ConstU32<6>;
}
parameter_types! {
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
pub const OperationalFeeMultiplier: u8 = 5;
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000);
pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128);
pub MaximumMultiplier: Multiplier = Bounded::max_value();
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = IdentityFee<Balance>;
Stephen Shelton
committed
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type FeeMultiplierUpdate = TargetedFeeAdjustment<
Self,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
MaximumMultiplier,
>;
impl pallet_asset_tx_payment::Config for Runtime {
type Fungibles = Assets;
type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter<
pallet_assets::BalanceToAssetBalance<Balances, Runtime, ConvertInto, Instance1>,
CreditToBlockAuthor,
>;
}
impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = Assets;
type OnChargeAssetTransaction = pallet_asset_conversion_tx_payment::AssetConversionAdapter<
Balances,
AssetConversion,
Native,
>;
}
impl pallet_skip_feeless_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}
pub const MinimumPeriod: Moment = SLOT_DURATION / 2;
impl pallet_timestamp::Config for Runtime {
type MinimumPeriod = MinimumPeriod;
type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
type EventHandler = (Staking, ImOnline);
pub struct SessionKeys {
pub grandpa: Grandpa,
pub babe: Babe,
pub im_online: ImOnline,
pub authority_discovery: AuthorityDiscovery,
impl pallet_session::Config for Runtime {
type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = pallet_staking::StashOf<Self>;
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, Staking>;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
impl pallet_session::historical::Config for Runtime {
type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
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,
);
}
pub const SessionsPerEra: sp_staking::SessionIndex = 6;
pub const BondingDuration: sp_staking::EraIndex = 24 * 28;
pub const SlashDeferDuration: sp_staking::EraIndex = 24 * 7; // 1/4 the bonding duration.
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
pub const MaxNominators: u32 = 64;
André Silva
committed
pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17);
pub const MaxControllersInDeprecationBatch: u32 = 5900;
pub OffchainRepeat: BlockNumber = 5;
/// Upper limit on the number of NPOS nominations.
const MAX_QUOTA_NOMINATIONS: u32 = 16;
pub struct StakingBenchmarkingConfig;
impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig {
type MaxNominators = ConstU32<1000>;
type MaxValidators = ConstU32<1000>;
}
impl pallet_staking::Config for Runtime {
type CurrencyBalance = Balance;
type UnixTime = Timestamp;
type CurrencyToVote = sp_staking::currency_to_vote::U128CurrencyToVote;
type RewardRemainder = Treasury;
type Slash = Treasury; // send the slashed funds to the treasury.
type Reward = (); // rewards are minted from the void
type SessionsPerEra = SessionsPerEra;
type BondingDuration = BondingDuration;
type SlashDeferDuration = SlashDeferDuration;
/// A super-majority of the council can cancel the slash.
type AdminOrigin = EitherOfDiverse<
pallet_collective::EnsureProportionAtLeast<AccountId, CouncilCollective, 3, 4>,
type SessionInterface = Self;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type MaxExposurePageSize = ConstU32<256>;
André Silva
committed
type OffendingValidatorsThreshold = OffendingValidatorsThreshold;
type ElectionProvider = ElectionProviderMultiPhase;
type GenesisElectionProvider = onchain::OnChainExecution<OnChainSeqPhragmen>;
type VoterList = VoterList;
type NominationsQuota = pallet_staking::FixedNominationsQuota<MAX_QUOTA_NOMINATIONS>;
// This a placeholder, to be introduced in the next PR as an instance of bags-list
type TargetList = pallet_staking::UseValidatorsMap<Self>;
type MaxUnlockingChunks = ConstU32<32>;
type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch;
type EventListeners = NominationPools;
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
type BenchmarkingConfig = StakingBenchmarkingConfig;
impl pallet_fast_unstake::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ControlOrigin = frame_system::EnsureRoot<AccountId>;
type BatchSize = ConstU32<64>;
type Deposit = ConstU128<{ DOLLARS }>;
Roman Useinov
committed
type Currency = Balances;
type Staking = Staking;
type MaxErasToCheckPerBlock = ConstU32<1>;
parameter_types! {
// phase durations. 1/4 of the last session for each.
pub const SignedPhase: u32 = EPOCH_DURATION_IN_BLOCKS / 4;
pub const UnsignedPhase: u32 = EPOCH_DURATION_IN_BLOCKS / 4;
// signed config
pub const SignedRewardBase: Balance = 1 * DOLLARS;
Gonçalo Pestana
committed
pub const SignedFixedDeposit: Balance = 1 * DOLLARS;
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
pub const SignedDepositByte: Balance = 1 * CENTS;
// miner configs
pub const MultiPhaseUnsignedPriority: TransactionPriority = StakingUnsignedPriority::get() - 1u64;
pub MinerMaxWeight: Weight = RuntimeBlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic.expect("Normal extrinsics have a weight limit configured; qed")
.saturating_sub(BlockExecutionWeight::get());
// Solution can occupy 90% of normal block size
pub MinerMaxLength: u32 = Perbill::from_rational(9u32, 10) *
*RuntimeBlockLength::get()
.max
.get(DispatchClass::Normal);
Georges
committed
frame_election_provider_support::generate_solution_type!(
pub struct NposSolution16::<
VoterIndex = u32,
TargetIndex = u16,
Accuracy = sp_runtime::PerU16,
MaxVoters = MaxElectingVotersSolution,
>(16)
parameter_types! {
// Note: the EPM in this runtime runs the election on-chain. The election bounds must be
// carefully set so that an election round fits in one block.
pub ElectionBoundsMultiPhase: ElectionBounds = ElectionBoundsBuilder::default()
.voters_count(10_000.into()).targets_count(1_500.into()).build();
pub ElectionBoundsOnChain: ElectionBounds = ElectionBoundsBuilder::default()
.voters_count(5_000.into()).targets_count(1_250.into()).build();
pub MaxNominations: u32 = <NposSolution16 as frame_election_provider_support::NposSolution>::LIMIT as u32;
pub MaxElectingVotersSolution: u32 = 40_000;
// The maximum winners that can be elected by the Election pallet which is equivalent to the
// maximum active validators the staking pallet can have.
pub MaxActiveValidators: u32 = 1000;
/// The numbers configured here could always be more than the the maximum limits of staking pallet
/// to ensure election snapshot will not run out of memory. For now, we set them to smaller values
/// since the staking is bounded and the weight pipeline takes hours for this single pallet.
pub struct ElectionProviderBenchmarkConfig;
impl pallet_election_provider_multi_phase::BenchmarkingConfig for ElectionProviderBenchmarkConfig {
const VOTERS: [u32; 2] = [1000, 2000];
const TARGETS: [u32; 2] = [500, 1000];
const ACTIVE_VOTERS: [u32; 2] = [500, 800];
const DESIRED_TARGETS: [u32; 2] = [200, 400];
const SNAPSHOT_MAXIMUM_VOTERS: u32 = 1000;
const MINER_MAXIMUM_VOTERS: u32 = 1000;
const MAXIMUM_TARGETS: u32 = 300;
/// Maximum number of iterations for balancing that will be executed in the embedded OCW
/// miner of election provider multi phase.
pub const MINER_MAX_ITERATIONS: u32 = 10;
/// A source of random balance for NposSolver, which is meant to be run by the OCW election miner.
pub struct OffchainRandomBalancing;
impl Get<Option<BalancingConfig>> for OffchainRandomBalancing {
fn get() -> Option<BalancingConfig> {
use sp_runtime::traits::TrailingZeroInput;
let iterations = match MINER_MAX_ITERATIONS {
let seed = sp_io::offchain::random_seed();
let random = <u32>::decode(&mut TrailingZeroInput::new(&seed))
.expect("input is padded with zeroes; qed") %
max.saturating_add(1);
random as usize
},
};
let config = BalancingConfig { iterations, tolerance: 0 };
Some(config)
pub struct OnChainSeqPhragmen;
impl onchain::Config for OnChainSeqPhragmen {
type System = Runtime;
type Solver = SequentialPhragmen<
AccountId,
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
>;
type DataProvider = <Runtime as pallet_election_provider_multi_phase::Config>::DataProvider;
type WeightInfo = frame_election_provider_support::weights::SubstrateWeight<Runtime>;
type MaxWinners = <Runtime as pallet_election_provider_multi_phase::Config>::MaxWinners;
type Bounds = ElectionBoundsOnChain;
impl pallet_election_provider_multi_phase::MinerConfig for Runtime {
type AccountId = AccountId;
type MaxLength = MinerMaxLength;
type MaxWeight = MinerMaxWeight;
type Solution = NposSolution16;
type MaxVotesPerVoter =
<<Self as pallet_election_provider_multi_phase::Config>::DataProvider as 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 Currency = Balances;
type SignedPhase = SignedPhase;
type UnsignedPhase = UnsignedPhase;
type BetterSignedThreshold = ();
type OffchainRepeat = OffchainRepeat;
type MinerTxPriority = MultiPhaseUnsignedPriority;
type SignedMaxSubmissions = ConstU32<10>;
type SignedRewardBase = SignedRewardBase;
Gonçalo Pestana
committed
type SignedDepositBase =
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
type SignedDepositByte = SignedDepositByte;
type SignedMaxRefunds = ConstU32<3>;
type SignedDepositWeight = ();
type SignedMaxWeight = MinerMaxWeight;
type SlashHandler = (); // burn slashes
type RewardHandler = (); // nothing to do upon rewards
type DataProvider = Staking;
type Fallback = onchain::OnChainExecution<OnChainSeqPhragmen>;
type GovernanceFallback = onchain::OnChainExecution<OnChainSeqPhragmen>;
type Solver = SequentialPhragmen<AccountId, SolutionAccuracyOf<Self>, OffchainRandomBalancing>;
type ForceOrigin = EnsureRootOrHalfCouncil;
type MaxWinners = MaxActiveValidators;
type ElectionBounds = ElectionBoundsMultiPhase;
type BenchmarkingConfig = ElectionProviderBenchmarkConfig;
type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight<Self>;
}
parameter_types! {
pub const BagThresholds: &'static [u64] = &voter_bags::THRESHOLDS;
}
type VoterBagsListInstance = pallet_bags_list::Instance1;
impl pallet_bags_list::Config<VoterBagsListInstance> for Runtime {
/// The voter bags-list is loosely kept up to date, and the real source of truth for the score
/// of each node is the staking pallet.
type ScoreProvider = Staking;
type BagThresholds = BagThresholds;
type WeightInfo = pallet_bags_list::weights::SubstrateWeight<Runtime>;
parameter_types! {
pub const PostUnbondPoolsWindow: u32 = 4;
pub const NominationPoolsPalletId: PalletId = PalletId(*b"py/nopls");
pub const MaxPointsToBalance: u8 = 10;
}
use sp_runtime::traits::Convert;
pub struct BalanceToU256;
impl Convert<Balance, sp_core::U256> for BalanceToU256 {
fn convert(balance: Balance) -> sp_core::U256 {
sp_core::U256::from(balance)
}
}
pub struct U256ToBalance;
impl Convert<sp_core::U256, Balance> for U256ToBalance {
fn convert(n: sp_core::U256) -> Balance {
n.try_into().unwrap_or(Balance::max_value())
}
}
impl pallet_nomination_pools::Config for Runtime {
type WeightInfo = ();
type RuntimeFreezeReason = RuntimeFreezeReason;
type RewardCounter = FixedU128;
type BalanceToU256 = BalanceToU256;
type U256ToBalance = U256ToBalance;
Roman Useinov
committed
type Staking = Staking;
type PostUnbondingPoolsWindow = PostUnbondPoolsWindow;
type MaxMetadataLen = ConstU32<256>;
type MaxUnbonding = ConstU32<8>;
type PalletId = NominationPoolsPalletId;
type MaxPointsToBalance = MaxPointsToBalance;
parameter_types! {
pub const VoteLockingPeriod: BlockNumber = 30 * DAYS;
}
impl pallet_conviction_voting::Config for Runtime {
type WeightInfo = pallet_conviction_voting::weights::SubstrateWeight<Self>;
type Currency = Balances;
type VoteLockingPeriod = VoteLockingPeriod;
type MaxVotes = ConstU32<512>;
type MaxTurnout = frame_support::traits::TotalIssuanceOf<Balances, Self::AccountId>;
type Polls = Referenda;
}
parameter_types! {
pub const AlarmInterval: BlockNumber = 1;
pub const SubmissionDeposit: Balance = 100 * DOLLARS;
pub const UndecidingTimeout: BlockNumber = 28 * DAYS;
}
pub struct TracksInfo;
impl pallet_referenda::TracksInfo<Balance, BlockNumber> for TracksInfo {
type RuntimeOrigin = <RuntimeOrigin as frame_support::traits::OriginTrait>::PalletsOrigin;
fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo<Balance, BlockNumber>)] {
static DATA: [(u16, pallet_referenda::TrackInfo<Balance, BlockNumber>); 1] = [(
0u16,
pallet_referenda::TrackInfo {
name: "root",
max_deciding: 1,
decision_deposit: 10,
prepare_period: 4,
decision_period: 4,
confirm_period: 2,
min_enactment_period: 4,
min_approval: pallet_referenda::Curve::LinearDecreasing {
length: Perbill::from_percent(100),
floor: Perbill::from_percent(50),
ceil: Perbill::from_percent(100),
min_support: pallet_referenda::Curve::LinearDecreasing {
length: Perbill::from_percent(100),
floor: Perbill::from_percent(0),
ceil: Perbill::from_percent(100),
},
},
)];
&DATA[..]
}
fn track_for(id: &Self::RuntimeOrigin) -> Result<Self::Id, ()> {
if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) {
match system_origin {
frame_system::RawOrigin::Root => Ok(0),
_ => Err(()),
}
} else {
Err(())
}
}
}
pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber);
impl pallet_referenda::Config for Runtime {
type WeightInfo = pallet_referenda::weights::SubstrateWeight<Self>;
type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = pallet_balances::Pallet<Self>;
type SubmitOrigin = EnsureSigned<AccountId>;
type CancelOrigin = EnsureRoot<AccountId>;
type KillOrigin = EnsureRoot<AccountId>;
type Slash = ();
type Votes = pallet_conviction_voting::VotesOf<Runtime>;
type Tally = pallet_conviction_voting::TallyOf<Runtime>;
type SubmissionDeposit = SubmissionDeposit;
type MaxQueued = ConstU32<100>;
type UndecidingTimeout = UndecidingTimeout;
type AlarmInterval = AlarmInterval;
type Tracks = TracksInfo;
impl pallet_referenda::Config<pallet_referenda::Instance2> for Runtime {
type WeightInfo = pallet_referenda::weights::SubstrateWeight<Self>;
type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = pallet_balances::Pallet<Self>;
type SubmitOrigin = EnsureSigned<AccountId>;