use crate::{inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND, shared};
use alloc::vec::Vec;
use codec::{Decode, Encode};
use frame_support::{pallet_prelude::*, DefaultNoBound};
use frame_system::pallet_prelude::*;
use polkadot_parachain_primitives::primitives::{
MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM,
};
use polkadot_primitives::{
ApprovalVotingParams, AsyncBackingParams, Balance, ExecutorParamError, ExecutorParams,
NodeFeatures, SessionIndex, LEGACY_MIN_BACKING_VOTES, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE,
ON_DEMAND_MAX_QUEUE_MAX_SIZE,
};
use sp_runtime::{traits::Zero, Perbill, Percent};
#[cfg(test)]
mod tests;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
pub mod migration;
pub use pallet::*;
use polkadot_primitives::SchedulerParams;
const LOG_TARGET: &str = "runtime::configuration";
const POV_SIZE_HARD_LIMIT: u32 = 16 * 1024 * 1024;
#[derive(
Clone,
Encode,
Decode,
PartialEq,
sp_core::RuntimeDebug,
scale_info::TypeInfo,
serde::Serialize,
serde::Deserialize,
)]
#[serde(deny_unknown_fields)]
pub struct HostConfiguration<BlockNumber> {
pub max_code_size: u32,
pub max_head_data_size: u32,
pub max_upward_queue_count: u32,
pub max_upward_queue_size: u32,
pub max_upward_message_size: u32,
pub max_upward_message_num_per_candidate: u32,
pub hrmp_max_message_num_per_candidate: u32,
#[cfg_attr(feature = "std", serde(alias = "validation_upgrade_frequency"))]
pub validation_upgrade_cooldown: BlockNumber,
pub validation_upgrade_delay: BlockNumber,
pub async_backing_params: AsyncBackingParams,
pub max_pov_size: u32,
pub max_downward_message_size: u32,
pub hrmp_max_parachain_outbound_channels: u32,
pub hrmp_sender_deposit: Balance,
pub hrmp_recipient_deposit: Balance,
pub hrmp_channel_max_capacity: u32,
pub hrmp_channel_max_total_size: u32,
pub hrmp_max_parachain_inbound_channels: u32,
pub hrmp_channel_max_message_size: u32,
pub executor_params: ExecutorParams,
pub code_retention_period: BlockNumber,
pub max_validators: Option<u32>,
pub dispute_period: SessionIndex,
pub dispute_post_conclusion_acceptance_period: BlockNumber,
pub no_show_slots: u32,
pub n_delay_tranches: u32,
pub zeroth_delay_tranche_width: u32,
pub needed_approvals: u32,
pub relay_vrf_modulo_samples: u32,
pub pvf_voting_ttl: SessionIndex,
pub minimum_validation_upgrade_delay: BlockNumber,
pub minimum_backing_votes: u32,
pub node_features: NodeFeatures,
pub approval_voting_params: ApprovalVotingParams,
pub scheduler_params: SchedulerParams<BlockNumber>,
}
impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber> {
fn default() -> Self {
let ret = Self {
async_backing_params: AsyncBackingParams {
max_candidate_depth: 0,
allowed_ancestry_len: 0,
},
no_show_slots: 1u32.into(),
validation_upgrade_cooldown: Default::default(),
validation_upgrade_delay: 2u32.into(),
code_retention_period: Default::default(),
max_code_size: MAX_CODE_SIZE,
max_pov_size: Default::default(),
max_head_data_size: Default::default(),
max_validators: None,
dispute_period: 6,
dispute_post_conclusion_acceptance_period: 100.into(),
n_delay_tranches: 1,
zeroth_delay_tranche_width: Default::default(),
needed_approvals: Default::default(),
relay_vrf_modulo_samples: Default::default(),
max_upward_queue_count: Default::default(),
max_upward_queue_size: Default::default(),
max_downward_message_size: Default::default(),
max_upward_message_size: Default::default(),
max_upward_message_num_per_candidate: Default::default(),
hrmp_sender_deposit: Default::default(),
hrmp_recipient_deposit: Default::default(),
hrmp_channel_max_capacity: Default::default(),
hrmp_channel_max_total_size: Default::default(),
hrmp_max_parachain_inbound_channels: Default::default(),
hrmp_channel_max_message_size: Default::default(),
hrmp_max_parachain_outbound_channels: Default::default(),
hrmp_max_message_num_per_candidate: Default::default(),
pvf_voting_ttl: 2u32.into(),
minimum_validation_upgrade_delay: 2.into(),
executor_params: Default::default(),
approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 1 },
minimum_backing_votes: LEGACY_MIN_BACKING_VOTES,
node_features: NodeFeatures::EMPTY,
scheduler_params: Default::default(),
};
#[cfg(feature = "runtime-benchmarks")]
let ret = ret.with_benchmarking_default();
ret
}
}
#[cfg(feature = "runtime-benchmarks")]
impl<BlockNumber: Default + From<u32>> HostConfiguration<BlockNumber> {
fn with_benchmarking_default(mut self) -> Self {
self.max_head_data_size = self.max_head_data_size.max(1 << 20);
self.max_downward_message_size = self.max_downward_message_size.max(1 << 16);
self.hrmp_channel_max_capacity = self.hrmp_channel_max_capacity.max(1000);
self.hrmp_channel_max_message_size = self.hrmp_channel_max_message_size.max(1 << 16);
self.hrmp_max_parachain_inbound_channels =
self.hrmp_max_parachain_inbound_channels.max(100);
self.hrmp_max_parachain_outbound_channels =
self.hrmp_max_parachain_outbound_channels.max(100);
self
}
}
#[derive(Debug)]
pub enum InconsistentError<BlockNumber> {
ZeroGroupRotationFrequency,
ZeroParasAvailabilityPeriod,
ZeroNoShowSlots,
MaxCodeSizeExceedHardLimit { max_code_size: u32 },
MaxHeadDataSizeExceedHardLimit { max_head_data_size: u32 },
MaxPovSizeExceedHardLimit { max_pov_size: u32 },
MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod {
minimum_validation_upgrade_delay: BlockNumber,
paras_availability_period: BlockNumber,
},
ValidationUpgradeDelayIsTooLow { validation_upgrade_delay: BlockNumber },
MaxUpwardMessageSizeExceeded { max_message_size: u32 },
MaxHorizontalMessageNumExceeded { max_message_num: u32 },
MaxUpwardMessageNumExceeded { max_message_num: u32 },
MaxHrmpOutboundChannelsExceeded,
MaxHrmpInboundChannelsExceeded,
ZeroMinimumBackingVotes,
InconsistentExecutorParams { inner: ExecutorParamError },
LookaheadZero,
OnDemandQueueSizeTooLarge,
ZeroDelayTranches,
}
impl<BlockNumber> HostConfiguration<BlockNumber>
where
BlockNumber: Zero + PartialOrd + core::fmt::Debug + Clone + From<u32>,
{
pub fn check_consistency(&self) -> Result<(), InconsistentError<BlockNumber>> {
use InconsistentError::*;
if self.scheduler_params.group_rotation_frequency.is_zero() {
return Err(ZeroGroupRotationFrequency)
}
if self.scheduler_params.paras_availability_period.is_zero() {
return Err(ZeroParasAvailabilityPeriod)
}
if self.no_show_slots.is_zero() {
return Err(ZeroNoShowSlots)
}
if self.max_code_size > MAX_CODE_SIZE {
return Err(MaxCodeSizeExceedHardLimit { max_code_size: self.max_code_size })
}
if self.max_head_data_size > MAX_HEAD_DATA_SIZE {
return Err(MaxHeadDataSizeExceedHardLimit {
max_head_data_size: self.max_head_data_size,
})
}
if self.max_pov_size > POV_SIZE_HARD_LIMIT {
return Err(MaxPovSizeExceedHardLimit { max_pov_size: self.max_pov_size })
}
if self.minimum_validation_upgrade_delay <= self.scheduler_params.paras_availability_period
{
return Err(MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod {
minimum_validation_upgrade_delay: self.minimum_validation_upgrade_delay.clone(),
paras_availability_period: self.scheduler_params.paras_availability_period.clone(),
})
}
if self.validation_upgrade_delay <= 1.into() {
return Err(ValidationUpgradeDelayIsTooLow {
validation_upgrade_delay: self.validation_upgrade_delay.clone(),
})
}
if self.max_upward_message_size > crate::inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND {
return Err(MaxUpwardMessageSizeExceeded {
max_message_size: self.max_upward_message_size,
})
}
if self.hrmp_max_message_num_per_candidate > MAX_HORIZONTAL_MESSAGE_NUM {
return Err(MaxHorizontalMessageNumExceeded {
max_message_num: self.hrmp_max_message_num_per_candidate,
})
}
if self.max_upward_message_num_per_candidate > MAX_UPWARD_MESSAGE_NUM {
return Err(MaxUpwardMessageNumExceeded {
max_message_num: self.max_upward_message_num_per_candidate,
})
}
if self.hrmp_max_parachain_outbound_channels > crate::hrmp::HRMP_MAX_OUTBOUND_CHANNELS_BOUND
{
return Err(MaxHrmpOutboundChannelsExceeded)
}
if self.hrmp_max_parachain_inbound_channels > crate::hrmp::HRMP_MAX_INBOUND_CHANNELS_BOUND {
return Err(MaxHrmpInboundChannelsExceeded)
}
if self.minimum_backing_votes.is_zero() {
return Err(ZeroMinimumBackingVotes)
}
if let Err(inner) = self.executor_params.check_consistency() {
return Err(InconsistentExecutorParams { inner })
}
if self.scheduler_params.lookahead == 0 {
return Err(LookaheadZero)
}
if self.scheduler_params.on_demand_queue_max_size > ON_DEMAND_MAX_QUEUE_MAX_SIZE {
return Err(OnDemandQueueSizeTooLarge)
}
if self.n_delay_tranches.is_zero() {
return Err(ZeroDelayTranches)
}
Ok(())
}
pub fn panic_if_not_consistent(&self) {
if let Err(err) = self.check_consistency() {
panic!("Host configuration is inconsistent: {:?}\nCfg:\n{:#?}", err, self);
}
}
}
pub trait WeightInfo {
fn set_config_with_block_number() -> Weight;
fn set_config_with_u32() -> Weight;
fn set_config_with_option_u32() -> Weight;
fn set_config_with_balance() -> Weight;
fn set_hrmp_open_request_ttl() -> Weight;
fn set_config_with_executor_params() -> Weight;
fn set_config_with_perbill() -> Weight;
fn set_node_feature() -> Weight;
fn set_config_with_scheduler_params() -> Weight;
}
pub struct TestWeightInfo;
impl WeightInfo for TestWeightInfo {
fn set_config_with_block_number() -> Weight {
Weight::MAX
}
fn set_config_with_u32() -> Weight {
Weight::MAX
}
fn set_config_with_option_u32() -> Weight {
Weight::MAX
}
fn set_config_with_balance() -> Weight {
Weight::MAX
}
fn set_hrmp_open_request_ttl() -> Weight {
Weight::MAX
}
fn set_config_with_executor_params() -> Weight {
Weight::MAX
}
fn set_config_with_perbill() -> Weight {
Weight::MAX
}
fn set_node_feature() -> Weight {
Weight::MAX
}
fn set_config_with_scheduler_params() -> Weight {
Weight::MAX
}
}
#[frame_support::pallet]
pub mod pallet {
use super::*;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(12);
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config + shared::Config {
type WeightInfo: WeightInfo;
}
#[pallet::error]
pub enum Error<T> {
InvalidNewValue,
}
#[pallet::storage]
#[pallet::whitelist_storage]
pub type ActiveConfig<T: Config> =
StorageValue<_, HostConfiguration<BlockNumberFor<T>>, ValueQuery>;
#[pallet::storage]
pub type PendingConfigs<T: Config> =
StorageValue<_, Vec<(SessionIndex, HostConfiguration<BlockNumberFor<T>>)>, ValueQuery>;
#[pallet::storage]
pub(crate) type BypassConsistencyCheck<T: Config> = StorageValue<_, bool, ValueQuery>;
#[pallet::genesis_config]
#[derive(DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
pub config: HostConfiguration<BlockNumberFor<T>>,
}
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
self.config.panic_if_not_consistent();
ActiveConfig::<T>::put(&self.config);
}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_validation_upgrade_cooldown(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.validation_upgrade_cooldown = new;
})
}
#[pallet::call_index(1)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_validation_upgrade_delay(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.validation_upgrade_delay = new;
})
}
#[pallet::call_index(2)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_code_retention_period(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.code_retention_period = new;
})
}
#[pallet::call_index(3)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_code_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_code_size = new;
})
}
#[pallet::call_index(4)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_pov_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_pov_size = new;
})
}
#[pallet::call_index(5)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_head_data_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_head_data_size = new;
})
}
#[pallet::call_index(6)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_coretime_cores(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::set_coretime_cores_unchecked(new)
}
#[pallet::call_index(8)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_group_rotation_frequency(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.group_rotation_frequency = new;
})
}
#[pallet::call_index(9)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_paras_availability_period(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.paras_availability_period = new;
})
}
#[pallet::call_index(11)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_scheduling_lookahead(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.lookahead = new;
})
}
#[pallet::call_index(12)]
#[pallet::weight((
T::WeightInfo::set_config_with_option_u32(),
DispatchClass::Operational,
))]
pub fn set_max_validators_per_core(
origin: OriginFor<T>,
new: Option<u32>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.max_validators_per_core = new;
})
}
#[pallet::call_index(13)]
#[pallet::weight((
T::WeightInfo::set_config_with_option_u32(),
DispatchClass::Operational,
))]
pub fn set_max_validators(origin: OriginFor<T>, new: Option<u32>) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_validators = new;
})
}
#[pallet::call_index(14)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_dispute_period(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.dispute_period = new;
})
}
#[pallet::call_index(15)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_dispute_post_conclusion_acceptance_period(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.dispute_post_conclusion_acceptance_period = new;
})
}
#[pallet::call_index(18)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_no_show_slots(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.no_show_slots = new;
})
}
#[pallet::call_index(19)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_n_delay_tranches(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.n_delay_tranches = new;
})
}
#[pallet::call_index(20)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_zeroth_delay_tranche_width(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.zeroth_delay_tranche_width = new;
})
}
#[pallet::call_index(21)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_needed_approvals(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.needed_approvals = new;
})
}
#[pallet::call_index(22)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_relay_vrf_modulo_samples(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.relay_vrf_modulo_samples = new;
})
}
#[pallet::call_index(23)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_upward_queue_count(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_upward_queue_count = new;
})
}
#[pallet::call_index(24)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_upward_queue_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
ensure!(new <= MAX_UPWARD_MESSAGE_SIZE_BOUND, Error::<T>::InvalidNewValue);
Self::schedule_config_update(|config| {
config.max_upward_queue_size = new;
})
}
#[pallet::call_index(25)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_downward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_downward_message_size = new;
})
}
#[pallet::call_index(27)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_upward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_upward_message_size = new;
})
}
#[pallet::call_index(28)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_max_upward_message_num_per_candidate(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.max_upward_message_num_per_candidate = new;
})
}
#[pallet::call_index(29)]
#[pallet::weight((
T::WeightInfo::set_hrmp_open_request_ttl(),
DispatchClass::Operational,
))]
pub fn set_hrmp_open_request_ttl(_origin: OriginFor<T>, _new: u32) -> DispatchResult {
Err("this doesn't have any effect".into())
}
#[pallet::call_index(30)]
#[pallet::weight((
T::WeightInfo::set_config_with_balance(),
DispatchClass::Operational,
))]
pub fn set_hrmp_sender_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_sender_deposit = new;
})
}
#[pallet::call_index(31)]
#[pallet::weight((
T::WeightInfo::set_config_with_balance(),
DispatchClass::Operational,
))]
pub fn set_hrmp_recipient_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_recipient_deposit = new;
})
}
#[pallet::call_index(32)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_hrmp_channel_max_capacity(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_channel_max_capacity = new;
})
}
#[pallet::call_index(33)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_hrmp_channel_max_total_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_channel_max_total_size = new;
})
}
#[pallet::call_index(34)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_hrmp_max_parachain_inbound_channels(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_max_parachain_inbound_channels = new;
})
}
#[pallet::call_index(36)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_hrmp_channel_max_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_channel_max_message_size = new;
})
}
#[pallet::call_index(37)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_hrmp_max_parachain_outbound_channels(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_max_parachain_outbound_channels = new;
})
}
#[pallet::call_index(39)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_hrmp_max_message_num_per_candidate(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.hrmp_max_message_num_per_candidate = new;
})
}
#[pallet::call_index(42)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational,
))]
pub fn set_pvf_voting_ttl(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.pvf_voting_ttl = new;
})
}
#[pallet::call_index(43)]
#[pallet::weight((
T::WeightInfo::set_config_with_block_number(),
DispatchClass::Operational,
))]
pub fn set_minimum_validation_upgrade_delay(
origin: OriginFor<T>,
new: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.minimum_validation_upgrade_delay = new;
})
}
#[pallet::call_index(44)]
#[pallet::weight((
T::DbWeight::get().writes(1),
DispatchClass::Operational,
))]
pub fn set_bypass_consistency_check(origin: OriginFor<T>, new: bool) -> DispatchResult {
ensure_root(origin)?;
BypassConsistencyCheck::<T>::put(new);
Ok(())
}
#[pallet::call_index(45)]
#[pallet::weight((
T::WeightInfo::set_config_with_option_u32(), DispatchClass::Operational,
))]
pub fn set_async_backing_params(
origin: OriginFor<T>,
new: AsyncBackingParams,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.async_backing_params = new;
})
}
#[pallet::call_index(46)]
#[pallet::weight((
T::WeightInfo::set_config_with_executor_params(),
DispatchClass::Operational,
))]
pub fn set_executor_params(origin: OriginFor<T>, new: ExecutorParams) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.executor_params = new;
})
}
#[pallet::call_index(47)]
#[pallet::weight((
T::WeightInfo::set_config_with_balance(),
DispatchClass::Operational,
))]
pub fn set_on_demand_base_fee(origin: OriginFor<T>, new: Balance) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.on_demand_base_fee = new;
})
}
#[pallet::call_index(48)]
#[pallet::weight((
T::WeightInfo::set_config_with_perbill(),
DispatchClass::Operational,
))]
pub fn set_on_demand_fee_variability(origin: OriginFor<T>, new: Perbill) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.on_demand_fee_variability = new;
})
}
#[pallet::call_index(49)]
#[pallet::weight((
T::WeightInfo::set_config_with_option_u32(),
DispatchClass::Operational,
))]
pub fn set_on_demand_queue_max_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.on_demand_queue_max_size = new;
})
}
#[pallet::call_index(50)]
#[pallet::weight((
T::WeightInfo::set_config_with_perbill(),
DispatchClass::Operational,
))]
pub fn set_on_demand_target_queue_utilization(
origin: OriginFor<T>,
new: Perbill,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params.on_demand_target_queue_utilization = new;
})
}
#[pallet::call_index(52)]
#[pallet::weight((
T::WeightInfo::set_config_with_u32(),
DispatchClass::Operational
))]
pub fn set_minimum_backing_votes(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.minimum_backing_votes = new;
})
}
#[pallet::call_index(53)]
#[pallet::weight((
T::WeightInfo::set_node_feature(),
DispatchClass::Operational
))]
pub fn set_node_feature(origin: OriginFor<T>, index: u8, value: bool) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
let index = usize::from(index);
if config.node_features.len() <= index {
config.node_features.resize(index + 1, false);
}
config.node_features.set(index, value);
})
}
#[pallet::call_index(54)]
#[pallet::weight((
T::WeightInfo::set_config_with_executor_params(),
DispatchClass::Operational,
))]
pub fn set_approval_voting_params(
origin: OriginFor<T>,
new: ApprovalVotingParams,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.approval_voting_params = new;
})
}
#[pallet::call_index(55)]
#[pallet::weight((
T::WeightInfo::set_config_with_scheduler_params(),
DispatchClass::Operational,
))]
pub fn set_scheduler_params(
origin: OriginFor<T>,
new: SchedulerParams<BlockNumberFor<T>>,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_config_update(|config| {
config.scheduler_params = new;
})
}
}
impl<T: Config> Pallet<T> {
pub fn set_coretime_cores_unchecked(new: u32) -> DispatchResult {
Self::schedule_config_update(|config| {
config.scheduler_params.num_cores = new;
})
}
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn integrity_test() {
assert_eq!(
&ActiveConfig::<T>::hashed_key(),
polkadot_primitives::well_known_keys::ACTIVE_CONFIG,
"`well_known_keys::ACTIVE_CONFIG` doesn't match key of `ActiveConfig`! Make sure that the name of the\
configuration pallet is `Configuration` in the runtime!",
);
}
}
}
pub struct SessionChangeOutcome<BlockNumber> {
pub prev_config: HostConfiguration<BlockNumber>,
pub new_config: Option<HostConfiguration<BlockNumber>>,
}
impl<T: Config> Pallet<T> {
pub(crate) fn initializer_initialize(_now: BlockNumberFor<T>) -> Weight {
Weight::zero()
}
pub(crate) fn initializer_finalize() {}
pub(crate) fn initializer_on_new_session(
session_index: &SessionIndex,
) -> SessionChangeOutcome<BlockNumberFor<T>> {
let pending_configs = PendingConfigs::<T>::get();
let prev_config = ActiveConfig::<T>::get();
if pending_configs.is_empty() {
return SessionChangeOutcome { prev_config, new_config: None }
}
let (mut past_and_present, future) = pending_configs
.into_iter()
.partition::<Vec<_>, _>(|&(apply_at_session, _)| apply_at_session <= *session_index);
if past_and_present.len() > 1 {
log::error!(
target: LOG_TARGET,
"Skipping applying configuration changes scheduled sessions in the past",
);
}
let new_config = past_and_present.pop().map(|(_, config)| config);
if let Some(ref new_config) = new_config {
ActiveConfig::<T>::put(new_config);
}
PendingConfigs::<T>::put(future);
SessionChangeOutcome { prev_config, new_config }
}
fn scheduled_session() -> SessionIndex {
shared::Pallet::<T>::scheduled_session()
}
pub fn force_set_active_config(config: HostConfiguration<BlockNumberFor<T>>) {
ActiveConfig::<T>::set(config);
}
#[inline(never)]
pub(crate) fn schedule_config_update(
updater: impl FnOnce(&mut HostConfiguration<BlockNumberFor<T>>),
) -> DispatchResult {
let mut pending_configs = PendingConfigs::<T>::get();
let mut base_config = pending_configs
.last()
.map(|(_, config)| config.clone())
.unwrap_or_else(ActiveConfig::<T>::get);
let base_config_consistent = base_config.check_consistency().is_ok();
updater(&mut base_config);
let new_config = base_config;
if BypassConsistencyCheck::<T>::get() {
log::warn!(
target: LOG_TARGET,
"Bypassing the consistency check for the configuration change!",
);
} else if let Err(e) = new_config.check_consistency() {
if base_config_consistent {
log::warn!(
target: LOG_TARGET,
"Configuration change rejected due to invalid configuration: {:?}",
e,
);
return Err(Error::<T>::InvalidNewValue.into())
} else {
log::warn!(
target: LOG_TARGET,
"The new configuration is broken but the old is broken as well. Proceeding",
);
}
}
let scheduled_session = Self::scheduled_session();
if let Some(&mut (_, ref mut config)) = pending_configs
.iter_mut()
.find(|&&mut (apply_at_session, _)| apply_at_session >= scheduled_session)
{
*config = new_config;
} else {
pending_configs.push((scheduled_session, new_config));
}
PendingConfigs::<T>::put(pending_configs);
Ok(())
}
}
pub struct ActiveConfigHrmpChannelSizeAndCapacityRatio<T, P>(core::marker::PhantomData<(T, P)>);
impl<T: crate::hrmp::pallet::Config, P: Get<Percent>> Get<(u32, u32)>
for ActiveConfigHrmpChannelSizeAndCapacityRatio<T, P>
{
fn get() -> (u32, u32) {
let config = ActiveConfig::<T>::get();
let percent = P::get();
(percent * config.hrmp_channel_max_message_size, percent * config.hrmp_channel_max_capacity)
}
}