1use crate::shared;
22use alloc::vec::Vec;
23use codec::{Decode, Encode};
24use frame_support::{pallet_prelude::*, DefaultNoBound};
25use frame_system::pallet_prelude::*;
26use polkadot_parachain_primitives::primitives::{
27 MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM,
28};
29use polkadot_primitives::{
30 ApprovalVotingParams, AsyncBackingParams, Balance, ExecutorParamError, ExecutorParams,
31 NodeFeatures, SessionIndex, LEGACY_MIN_BACKING_VOTES, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE,
32 ON_DEMAND_MAX_QUEUE_MAX_SIZE,
33};
34use sp_runtime::{traits::Zero, Perbill, Percent};
35
36#[cfg(test)]
37mod tests;
38
39#[cfg(feature = "runtime-benchmarks")]
40mod benchmarking;
41
42pub mod migration;
43
44pub use pallet::*;
45use polkadot_primitives::SchedulerParams;
46
47const LOG_TARGET: &str = "runtime::configuration";
48
49const POV_SIZE_HARD_LIMIT: u32 = 16 * 1024 * 1024;
52
53pub(crate) const MAX_VALIDATION_CODE_COMPRESSION_RATIO: u32 = 10;
55
56#[derive(
58 Clone,
59 Encode,
60 Decode,
61 PartialEq,
62 sp_core::RuntimeDebug,
63 scale_info::TypeInfo,
64 serde::Serialize,
65 serde::Deserialize,
66)]
67#[serde(deny_unknown_fields)]
68pub struct HostConfiguration<BlockNumber> {
69 pub max_code_size: u32,
81 pub max_head_data_size: u32,
83 pub max_upward_queue_count: u32,
85 pub max_upward_queue_size: u32,
89 pub max_upward_message_size: u32,
93 pub max_upward_message_num_per_candidate: u32,
97 pub hrmp_max_message_num_per_candidate: u32,
101 #[cfg_attr(feature = "std", serde(alias = "validation_upgrade_frequency"))]
112 pub validation_upgrade_cooldown: BlockNumber,
113 pub validation_upgrade_delay: BlockNumber,
140 pub async_backing_params: AsyncBackingParams,
142
143 pub max_pov_size: u32,
149 pub max_downward_message_size: u32,
156 pub hrmp_max_parachain_outbound_channels: u32,
158 pub hrmp_sender_deposit: Balance,
160 pub hrmp_recipient_deposit: Balance,
162 pub hrmp_channel_max_capacity: u32,
164 pub hrmp_channel_max_total_size: u32,
166 pub hrmp_max_parachain_inbound_channels: u32,
168 pub hrmp_channel_max_message_size: u32,
172 pub executor_params: ExecutorParams,
174
175 pub code_retention_period: BlockNumber,
182
183 pub max_validators: Option<u32>,
187 pub dispute_period: SessionIndex,
189 pub dispute_post_conclusion_acceptance_period: BlockNumber,
191 pub no_show_slots: u32,
196 pub n_delay_tranches: u32,
198 pub zeroth_delay_tranche_width: u32,
201 pub needed_approvals: u32,
203 pub relay_vrf_modulo_samples: u32,
205 pub pvf_voting_ttl: SessionIndex,
211 pub minimum_validation_upgrade_delay: BlockNumber,
228 pub minimum_backing_votes: u32,
231 pub node_features: NodeFeatures,
233 pub approval_voting_params: ApprovalVotingParams,
235 pub scheduler_params: SchedulerParams<BlockNumber>,
237}
238
239impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber> {
240 fn default() -> Self {
241 let ret = Self {
242 async_backing_params: AsyncBackingParams {
243 max_candidate_depth: 0,
244 allowed_ancestry_len: 0,
245 },
246 no_show_slots: 1u32.into(),
247 validation_upgrade_cooldown: Default::default(),
248 validation_upgrade_delay: 2u32.into(),
249 code_retention_period: Default::default(),
250 max_code_size: MAX_CODE_SIZE,
251 max_pov_size: Default::default(),
252 max_head_data_size: Default::default(),
253 max_validators: None,
254 dispute_period: 6,
255 dispute_post_conclusion_acceptance_period: 100.into(),
256 n_delay_tranches: 1,
257 zeroth_delay_tranche_width: Default::default(),
258 needed_approvals: Default::default(),
259 relay_vrf_modulo_samples: Default::default(),
260 max_upward_queue_count: Default::default(),
261 max_upward_queue_size: Default::default(),
262 max_downward_message_size: Default::default(),
263 max_upward_message_size: Default::default(),
264 max_upward_message_num_per_candidate: Default::default(),
265 hrmp_sender_deposit: Default::default(),
266 hrmp_recipient_deposit: Default::default(),
267 hrmp_channel_max_capacity: Default::default(),
268 hrmp_channel_max_total_size: Default::default(),
269 hrmp_max_parachain_inbound_channels: Default::default(),
270 hrmp_channel_max_message_size: Default::default(),
271 hrmp_max_parachain_outbound_channels: Default::default(),
272 hrmp_max_message_num_per_candidate: Default::default(),
273 pvf_voting_ttl: 2u32.into(),
274 minimum_validation_upgrade_delay: 2.into(),
275 executor_params: Default::default(),
276 approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 1 },
277 minimum_backing_votes: LEGACY_MIN_BACKING_VOTES,
278 node_features: NodeFeatures::EMPTY,
279 scheduler_params: Default::default(),
280 };
281
282 #[cfg(feature = "runtime-benchmarks")]
283 let ret = ret.with_benchmarking_default();
284 ret
285 }
286}
287
288#[cfg(feature = "runtime-benchmarks")]
289impl<BlockNumber: Default + From<u32>> HostConfiguration<BlockNumber> {
290 fn with_benchmarking_default(mut self) -> Self {
295 self.max_head_data_size = self.max_head_data_size.max(1 << 20);
296 self.max_downward_message_size = self.max_downward_message_size.max(1 << 16);
297 self.hrmp_channel_max_capacity = self.hrmp_channel_max_capacity.max(1000);
298 self.hrmp_channel_max_message_size = self.hrmp_channel_max_message_size.max(1 << 16);
299 self.hrmp_max_parachain_inbound_channels =
300 self.hrmp_max_parachain_inbound_channels.max(100);
301 self.hrmp_max_parachain_outbound_channels =
302 self.hrmp_max_parachain_outbound_channels.max(100);
303 self
304 }
305}
306
307#[derive(Debug)]
309pub enum InconsistentError<BlockNumber> {
310 ZeroGroupRotationFrequency,
312 ZeroParasAvailabilityPeriod,
314 ZeroNoShowSlots,
316 MaxCodeSizeExceedHardLimit { max_code_size: u32 },
318 MaxHeadDataSizeExceedHardLimit { max_head_data_size: u32 },
320 MaxPovSizeExceedHardLimit { max_pov_size: u32 },
322 MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod {
324 minimum_validation_upgrade_delay: BlockNumber,
325 paras_availability_period: BlockNumber,
326 },
327 ValidationUpgradeDelayIsTooLow { validation_upgrade_delay: BlockNumber },
329 MaxUpwardMessageSizeExceeded { max_message_size: u32 },
333 MaxHorizontalMessageNumExceeded { max_message_num: u32 },
335 MaxUpwardMessageNumExceeded { max_message_num: u32 },
337 MaxHrmpOutboundChannelsExceeded,
339 MaxHrmpInboundChannelsExceeded,
341 ZeroMinimumBackingVotes,
343 InconsistentExecutorParams { inner: ExecutorParamError },
345 LookaheadZero,
347 OnDemandQueueSizeTooLarge,
349 ZeroDelayTranches,
351}
352
353impl<BlockNumber> HostConfiguration<BlockNumber>
354where
355 BlockNumber: Zero + PartialOrd + core::fmt::Debug + Clone + From<u32>,
356{
357 pub fn check_consistency(&self) -> Result<(), InconsistentError<BlockNumber>> {
363 use InconsistentError::*;
364
365 if self.scheduler_params.group_rotation_frequency.is_zero() {
366 return Err(ZeroGroupRotationFrequency)
367 }
368
369 if self.scheduler_params.paras_availability_period.is_zero() {
370 return Err(ZeroParasAvailabilityPeriod)
371 }
372
373 if self.no_show_slots.is_zero() {
374 return Err(ZeroNoShowSlots)
375 }
376
377 if self.max_code_size > MAX_CODE_SIZE {
378 return Err(MaxCodeSizeExceedHardLimit { max_code_size: self.max_code_size })
379 }
380
381 if self.max_head_data_size > MAX_HEAD_DATA_SIZE {
382 return Err(MaxHeadDataSizeExceedHardLimit {
383 max_head_data_size: self.max_head_data_size,
384 })
385 }
386
387 if self.max_pov_size > POV_SIZE_HARD_LIMIT {
388 return Err(MaxPovSizeExceedHardLimit { max_pov_size: self.max_pov_size })
389 }
390
391 if self.minimum_validation_upgrade_delay <= self.scheduler_params.paras_availability_period
392 {
393 return Err(MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod {
394 minimum_validation_upgrade_delay: self.minimum_validation_upgrade_delay.clone(),
395 paras_availability_period: self.scheduler_params.paras_availability_period.clone(),
396 })
397 }
398
399 if self.validation_upgrade_delay <= 1.into() {
400 return Err(ValidationUpgradeDelayIsTooLow {
401 validation_upgrade_delay: self.validation_upgrade_delay.clone(),
402 })
403 }
404
405 if self.max_upward_message_size > crate::inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND {
406 return Err(MaxUpwardMessageSizeExceeded {
407 max_message_size: self.max_upward_message_size,
408 })
409 }
410
411 if self.hrmp_max_message_num_per_candidate > MAX_HORIZONTAL_MESSAGE_NUM {
412 return Err(MaxHorizontalMessageNumExceeded {
413 max_message_num: self.hrmp_max_message_num_per_candidate,
414 })
415 }
416
417 if self.max_upward_message_num_per_candidate > MAX_UPWARD_MESSAGE_NUM {
418 return Err(MaxUpwardMessageNumExceeded {
419 max_message_num: self.max_upward_message_num_per_candidate,
420 })
421 }
422
423 if self.hrmp_max_parachain_outbound_channels > crate::hrmp::HRMP_MAX_OUTBOUND_CHANNELS_BOUND
424 {
425 return Err(MaxHrmpOutboundChannelsExceeded)
426 }
427
428 if self.hrmp_max_parachain_inbound_channels > crate::hrmp::HRMP_MAX_INBOUND_CHANNELS_BOUND {
429 return Err(MaxHrmpInboundChannelsExceeded)
430 }
431
432 if self.minimum_backing_votes.is_zero() {
433 return Err(ZeroMinimumBackingVotes)
434 }
435
436 if let Err(inner) = self.executor_params.check_consistency() {
437 return Err(InconsistentExecutorParams { inner })
438 }
439
440 if self.scheduler_params.lookahead == 0 {
441 return Err(LookaheadZero)
442 }
443
444 if self.scheduler_params.on_demand_queue_max_size > ON_DEMAND_MAX_QUEUE_MAX_SIZE {
445 return Err(OnDemandQueueSizeTooLarge)
446 }
447
448 if self.n_delay_tranches.is_zero() {
449 return Err(ZeroDelayTranches)
450 }
451
452 Ok(())
453 }
454
455 pub fn panic_if_not_consistent(&self) {
461 if let Err(err) = self.check_consistency() {
462 panic!("Host configuration is inconsistent: {:?}\nCfg:\n{:#?}", err, self);
463 }
464 }
465}
466
467pub trait WeightInfo {
468 fn set_config_with_block_number() -> Weight;
469 fn set_config_with_u32() -> Weight;
470 fn set_config_with_option_u32() -> Weight;
471 fn set_config_with_balance() -> Weight;
472 fn set_hrmp_open_request_ttl() -> Weight;
473 fn set_config_with_executor_params() -> Weight;
474 fn set_config_with_perbill() -> Weight;
475 fn set_node_feature() -> Weight;
476 fn set_config_with_scheduler_params() -> Weight;
477}
478
479pub struct TestWeightInfo;
480impl WeightInfo for TestWeightInfo {
481 fn set_config_with_block_number() -> Weight {
482 Weight::MAX
483 }
484 fn set_config_with_u32() -> Weight {
485 Weight::MAX
486 }
487 fn set_config_with_option_u32() -> Weight {
488 Weight::MAX
489 }
490 fn set_config_with_balance() -> Weight {
491 Weight::MAX
492 }
493 fn set_hrmp_open_request_ttl() -> Weight {
494 Weight::MAX
495 }
496 fn set_config_with_executor_params() -> Weight {
497 Weight::MAX
498 }
499 fn set_config_with_perbill() -> Weight {
500 Weight::MAX
501 }
502 fn set_node_feature() -> Weight {
503 Weight::MAX
504 }
505 fn set_config_with_scheduler_params() -> Weight {
506 Weight::MAX
507 }
508}
509
510#[frame_support::pallet]
511pub mod pallet {
512 use super::*;
513
514 const STORAGE_VERSION: StorageVersion = StorageVersion::new(12);
531
532 #[pallet::pallet]
533 #[pallet::storage_version(STORAGE_VERSION)]
534 #[pallet::without_storage_info]
535 pub struct Pallet<T>(_);
536
537 #[pallet::config]
538 pub trait Config: frame_system::Config + shared::Config {
539 type WeightInfo: WeightInfo;
541 }
542
543 #[pallet::error]
544 pub enum Error<T> {
545 InvalidNewValue,
547 }
548
549 #[pallet::storage]
551 #[pallet::whitelist_storage]
552 pub type ActiveConfig<T: Config> =
553 StorageValue<_, HostConfiguration<BlockNumberFor<T>>, ValueQuery>;
554
555 #[pallet::storage]
563 pub type PendingConfigs<T: Config> =
564 StorageValue<_, Vec<(SessionIndex, HostConfiguration<BlockNumberFor<T>>)>, ValueQuery>;
565
566 #[pallet::storage]
569 pub(crate) type BypassConsistencyCheck<T: Config> = StorageValue<_, bool, ValueQuery>;
570
571 #[pallet::genesis_config]
572 #[derive(DefaultNoBound)]
573 pub struct GenesisConfig<T: Config> {
574 pub config: HostConfiguration<BlockNumberFor<T>>,
575 }
576
577 #[pallet::genesis_build]
578 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
579 fn build(&self) {
580 self.config.panic_if_not_consistent();
581 ActiveConfig::<T>::put(&self.config);
582 }
583 }
584
585 #[pallet::call]
586 impl<T: Config> Pallet<T> {
587 #[pallet::call_index(0)]
589 #[pallet::weight((
590 T::WeightInfo::set_config_with_block_number(),
591 DispatchClass::Operational,
592 ))]
593 pub fn set_validation_upgrade_cooldown(
594 origin: OriginFor<T>,
595 new: BlockNumberFor<T>,
596 ) -> DispatchResult {
597 ensure_root(origin)?;
598 Self::schedule_config_update(|config| {
599 config.validation_upgrade_cooldown = new;
600 })
601 }
602
603 #[pallet::call_index(1)]
605 #[pallet::weight((
606 T::WeightInfo::set_config_with_block_number(),
607 DispatchClass::Operational,
608 ))]
609 pub fn set_validation_upgrade_delay(
610 origin: OriginFor<T>,
611 new: BlockNumberFor<T>,
612 ) -> DispatchResult {
613 ensure_root(origin)?;
614 Self::schedule_config_update(|config| {
615 config.validation_upgrade_delay = new;
616 })
617 }
618
619 #[pallet::call_index(2)]
621 #[pallet::weight((
622 T::WeightInfo::set_config_with_block_number(),
623 DispatchClass::Operational,
624 ))]
625 pub fn set_code_retention_period(
626 origin: OriginFor<T>,
627 new: BlockNumberFor<T>,
628 ) -> DispatchResult {
629 ensure_root(origin)?;
630 Self::schedule_config_update(|config| {
631 config.code_retention_period = new;
632 })
633 }
634
635 #[pallet::call_index(3)]
637 #[pallet::weight((
638 T::WeightInfo::set_config_with_u32(),
639 DispatchClass::Operational,
640 ))]
641 pub fn set_max_code_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
642 ensure_root(origin)?;
643 Self::schedule_config_update(|config| {
644 config.max_code_size = new;
645 })
646 }
647
648 #[pallet::call_index(4)]
650 #[pallet::weight((
651 T::WeightInfo::set_config_with_u32(),
652 DispatchClass::Operational,
653 ))]
654 pub fn set_max_pov_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
655 ensure_root(origin)?;
656 Self::schedule_config_update(|config| {
657 config.max_pov_size = new;
658 })
659 }
660
661 #[pallet::call_index(5)]
663 #[pallet::weight((
664 T::WeightInfo::set_config_with_u32(),
665 DispatchClass::Operational,
666 ))]
667 pub fn set_max_head_data_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
668 ensure_root(origin)?;
669 Self::schedule_config_update(|config| {
670 config.max_head_data_size = new;
671 })
672 }
673
674 #[pallet::call_index(6)]
679 #[pallet::weight((
680 T::WeightInfo::set_config_with_u32(),
681 DispatchClass::Operational,
682 ))]
683 pub fn set_coretime_cores(origin: OriginFor<T>, new: u32) -> DispatchResult {
684 ensure_root(origin)?;
685 Self::set_coretime_cores_unchecked(new)
686 }
687
688 #[pallet::call_index(8)]
692 #[pallet::weight((
693 T::WeightInfo::set_config_with_block_number(),
694 DispatchClass::Operational,
695 ))]
696 pub fn set_group_rotation_frequency(
697 origin: OriginFor<T>,
698 new: BlockNumberFor<T>,
699 ) -> DispatchResult {
700 ensure_root(origin)?;
701 Self::schedule_config_update(|config| {
702 config.scheduler_params.group_rotation_frequency = new;
703 })
704 }
705
706 #[pallet::call_index(9)]
708 #[pallet::weight((
709 T::WeightInfo::set_config_with_block_number(),
710 DispatchClass::Operational,
711 ))]
712 pub fn set_paras_availability_period(
713 origin: OriginFor<T>,
714 new: BlockNumberFor<T>,
715 ) -> DispatchResult {
716 ensure_root(origin)?;
717 Self::schedule_config_update(|config| {
718 config.scheduler_params.paras_availability_period = new;
719 })
720 }
721
722 #[pallet::call_index(11)]
724 #[pallet::weight((
725 T::WeightInfo::set_config_with_u32(),
726 DispatchClass::Operational,
727 ))]
728 pub fn set_scheduling_lookahead(origin: OriginFor<T>, new: u32) -> DispatchResult {
729 ensure_root(origin)?;
730 Self::schedule_config_update(|config| {
731 config.scheduler_params.lookahead = new;
732 })
733 }
734
735 #[pallet::call_index(12)]
737 #[pallet::weight((
738 T::WeightInfo::set_config_with_option_u32(),
739 DispatchClass::Operational,
740 ))]
741 pub fn set_max_validators_per_core(
742 origin: OriginFor<T>,
743 new: Option<u32>,
744 ) -> DispatchResult {
745 ensure_root(origin)?;
746 Self::schedule_config_update(|config| {
747 config.scheduler_params.max_validators_per_core = new;
748 })
749 }
750
751 #[pallet::call_index(13)]
753 #[pallet::weight((
754 T::WeightInfo::set_config_with_option_u32(),
755 DispatchClass::Operational,
756 ))]
757 pub fn set_max_validators(origin: OriginFor<T>, new: Option<u32>) -> DispatchResult {
758 ensure_root(origin)?;
759 Self::schedule_config_update(|config| {
760 config.max_validators = new;
761 })
762 }
763
764 #[pallet::call_index(14)]
766 #[pallet::weight((
767 T::WeightInfo::set_config_with_u32(),
768 DispatchClass::Operational,
769 ))]
770 pub fn set_dispute_period(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
771 ensure_root(origin)?;
772 Self::schedule_config_update(|config| {
773 config.dispute_period = new;
774 })
775 }
776
777 #[pallet::call_index(15)]
779 #[pallet::weight((
780 T::WeightInfo::set_config_with_block_number(),
781 DispatchClass::Operational,
782 ))]
783 pub fn set_dispute_post_conclusion_acceptance_period(
784 origin: OriginFor<T>,
785 new: BlockNumberFor<T>,
786 ) -> DispatchResult {
787 ensure_root(origin)?;
788 Self::schedule_config_update(|config| {
789 config.dispute_post_conclusion_acceptance_period = new;
790 })
791 }
792
793 #[pallet::call_index(18)]
796 #[pallet::weight((
797 T::WeightInfo::set_config_with_u32(),
798 DispatchClass::Operational,
799 ))]
800 pub fn set_no_show_slots(origin: OriginFor<T>, new: u32) -> DispatchResult {
801 ensure_root(origin)?;
802 Self::schedule_config_update(|config| {
803 config.no_show_slots = new;
804 })
805 }
806
807 #[pallet::call_index(19)]
809 #[pallet::weight((
810 T::WeightInfo::set_config_with_u32(),
811 DispatchClass::Operational,
812 ))]
813 pub fn set_n_delay_tranches(origin: OriginFor<T>, new: u32) -> DispatchResult {
814 ensure_root(origin)?;
815 Self::schedule_config_update(|config| {
816 config.n_delay_tranches = new;
817 })
818 }
819
820 #[pallet::call_index(20)]
822 #[pallet::weight((
823 T::WeightInfo::set_config_with_u32(),
824 DispatchClass::Operational,
825 ))]
826 pub fn set_zeroth_delay_tranche_width(origin: OriginFor<T>, new: u32) -> DispatchResult {
827 ensure_root(origin)?;
828 Self::schedule_config_update(|config| {
829 config.zeroth_delay_tranche_width = new;
830 })
831 }
832
833 #[pallet::call_index(21)]
835 #[pallet::weight((
836 T::WeightInfo::set_config_with_u32(),
837 DispatchClass::Operational,
838 ))]
839 pub fn set_needed_approvals(origin: OriginFor<T>, new: u32) -> DispatchResult {
840 ensure_root(origin)?;
841 Self::schedule_config_update(|config| {
842 config.needed_approvals = new;
843 })
844 }
845
846 #[pallet::call_index(22)]
848 #[pallet::weight((
849 T::WeightInfo::set_config_with_u32(),
850 DispatchClass::Operational,
851 ))]
852 pub fn set_relay_vrf_modulo_samples(origin: OriginFor<T>, new: u32) -> DispatchResult {
853 ensure_root(origin)?;
854 Self::schedule_config_update(|config| {
855 config.relay_vrf_modulo_samples = new;
856 })
857 }
858
859 #[pallet::call_index(23)]
861 #[pallet::weight((
862 T::WeightInfo::set_config_with_u32(),
863 DispatchClass::Operational,
864 ))]
865 pub fn set_max_upward_queue_count(origin: OriginFor<T>, new: u32) -> DispatchResult {
866 ensure_root(origin)?;
867 Self::schedule_config_update(|config| {
868 config.max_upward_queue_count = new;
869 })
870 }
871
872 #[pallet::call_index(24)]
875 #[pallet::weight((
876 T::WeightInfo::set_config_with_u32(),
877 DispatchClass::Operational,
878 ))]
879 pub fn set_max_upward_queue_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
880 ensure_root(origin)?;
881
882 Self::schedule_config_update(|config| {
883 config.max_upward_queue_size = new;
884 })
885 }
886
887 #[pallet::call_index(25)]
889 #[pallet::weight((
890 T::WeightInfo::set_config_with_u32(),
891 DispatchClass::Operational,
892 ))]
893 pub fn set_max_downward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
894 ensure_root(origin)?;
895 Self::schedule_config_update(|config| {
896 config.max_downward_message_size = new;
897 })
898 }
899
900 #[pallet::call_index(27)]
902 #[pallet::weight((
903 T::WeightInfo::set_config_with_u32(),
904 DispatchClass::Operational,
905 ))]
906 pub fn set_max_upward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
907 ensure_root(origin)?;
908 Self::schedule_config_update(|config| {
909 config.max_upward_message_size = new;
910 })
911 }
912
913 #[pallet::call_index(28)]
915 #[pallet::weight((
916 T::WeightInfo::set_config_with_u32(),
917 DispatchClass::Operational,
918 ))]
919 pub fn set_max_upward_message_num_per_candidate(
920 origin: OriginFor<T>,
921 new: u32,
922 ) -> DispatchResult {
923 ensure_root(origin)?;
924 Self::schedule_config_update(|config| {
925 config.max_upward_message_num_per_candidate = new;
926 })
927 }
928
929 #[pallet::call_index(29)]
931 #[pallet::weight((
932 T::WeightInfo::set_hrmp_open_request_ttl(),
933 DispatchClass::Operational,
934 ))]
935 pub fn set_hrmp_open_request_ttl(_origin: OriginFor<T>, _new: u32) -> DispatchResult {
938 Err("this doesn't have any effect".into())
939 }
940
941 #[pallet::call_index(30)]
943 #[pallet::weight((
944 T::WeightInfo::set_config_with_balance(),
945 DispatchClass::Operational,
946 ))]
947 pub fn set_hrmp_sender_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
948 ensure_root(origin)?;
949 Self::schedule_config_update(|config| {
950 config.hrmp_sender_deposit = new;
951 })
952 }
953
954 #[pallet::call_index(31)]
957 #[pallet::weight((
958 T::WeightInfo::set_config_with_balance(),
959 DispatchClass::Operational,
960 ))]
961 pub fn set_hrmp_recipient_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
962 ensure_root(origin)?;
963 Self::schedule_config_update(|config| {
964 config.hrmp_recipient_deposit = new;
965 })
966 }
967
968 #[pallet::call_index(32)]
970 #[pallet::weight((
971 T::WeightInfo::set_config_with_u32(),
972 DispatchClass::Operational,
973 ))]
974 pub fn set_hrmp_channel_max_capacity(origin: OriginFor<T>, new: u32) -> DispatchResult {
975 ensure_root(origin)?;
976 Self::schedule_config_update(|config| {
977 config.hrmp_channel_max_capacity = new;
978 })
979 }
980
981 #[pallet::call_index(33)]
983 #[pallet::weight((
984 T::WeightInfo::set_config_with_u32(),
985 DispatchClass::Operational,
986 ))]
987 pub fn set_hrmp_channel_max_total_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
988 ensure_root(origin)?;
989 Self::schedule_config_update(|config| {
990 config.hrmp_channel_max_total_size = new;
991 })
992 }
993
994 #[pallet::call_index(34)]
996 #[pallet::weight((
997 T::WeightInfo::set_config_with_u32(),
998 DispatchClass::Operational,
999 ))]
1000 pub fn set_hrmp_max_parachain_inbound_channels(
1001 origin: OriginFor<T>,
1002 new: u32,
1003 ) -> DispatchResult {
1004 ensure_root(origin)?;
1005 Self::schedule_config_update(|config| {
1006 config.hrmp_max_parachain_inbound_channels = new;
1007 })
1008 }
1009
1010 #[pallet::call_index(36)]
1012 #[pallet::weight((
1013 T::WeightInfo::set_config_with_u32(),
1014 DispatchClass::Operational,
1015 ))]
1016 pub fn set_hrmp_channel_max_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
1017 ensure_root(origin)?;
1018 Self::schedule_config_update(|config| {
1019 config.hrmp_channel_max_message_size = new;
1020 })
1021 }
1022
1023 #[pallet::call_index(37)]
1025 #[pallet::weight((
1026 T::WeightInfo::set_config_with_u32(),
1027 DispatchClass::Operational,
1028 ))]
1029 pub fn set_hrmp_max_parachain_outbound_channels(
1030 origin: OriginFor<T>,
1031 new: u32,
1032 ) -> DispatchResult {
1033 ensure_root(origin)?;
1034 Self::schedule_config_update(|config| {
1035 config.hrmp_max_parachain_outbound_channels = new;
1036 })
1037 }
1038
1039 #[pallet::call_index(39)]
1041 #[pallet::weight((
1042 T::WeightInfo::set_config_with_u32(),
1043 DispatchClass::Operational,
1044 ))]
1045 pub fn set_hrmp_max_message_num_per_candidate(
1046 origin: OriginFor<T>,
1047 new: u32,
1048 ) -> DispatchResult {
1049 ensure_root(origin)?;
1050 Self::schedule_config_update(|config| {
1051 config.hrmp_max_message_num_per_candidate = new;
1052 })
1053 }
1054
1055 #[pallet::call_index(42)]
1057 #[pallet::weight((
1058 T::WeightInfo::set_config_with_u32(),
1059 DispatchClass::Operational,
1060 ))]
1061 pub fn set_pvf_voting_ttl(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
1062 ensure_root(origin)?;
1063 Self::schedule_config_update(|config| {
1064 config.pvf_voting_ttl = new;
1065 })
1066 }
1067
1068 #[pallet::call_index(43)]
1073 #[pallet::weight((
1074 T::WeightInfo::set_config_with_block_number(),
1075 DispatchClass::Operational,
1076 ))]
1077 pub fn set_minimum_validation_upgrade_delay(
1078 origin: OriginFor<T>,
1079 new: BlockNumberFor<T>,
1080 ) -> DispatchResult {
1081 ensure_root(origin)?;
1082 Self::schedule_config_update(|config| {
1083 config.minimum_validation_upgrade_delay = new;
1084 })
1085 }
1086
1087 #[pallet::call_index(44)]
1090 #[pallet::weight((
1091 T::DbWeight::get().writes(1),
1092 DispatchClass::Operational,
1093 ))]
1094 pub fn set_bypass_consistency_check(origin: OriginFor<T>, new: bool) -> DispatchResult {
1095 ensure_root(origin)?;
1096 BypassConsistencyCheck::<T>::put(new);
1097 Ok(())
1098 }
1099
1100 #[pallet::call_index(45)]
1102 #[pallet::weight((
1103 T::WeightInfo::set_config_with_option_u32(), DispatchClass::Operational,
1105 ))]
1106 pub fn set_async_backing_params(
1107 origin: OriginFor<T>,
1108 new: AsyncBackingParams,
1109 ) -> DispatchResult {
1110 ensure_root(origin)?;
1111 Self::schedule_config_update(|config| {
1112 config.async_backing_params = new;
1113 })
1114 }
1115
1116 #[pallet::call_index(46)]
1118 #[pallet::weight((
1119 T::WeightInfo::set_config_with_executor_params(),
1120 DispatchClass::Operational,
1121 ))]
1122 pub fn set_executor_params(origin: OriginFor<T>, new: ExecutorParams) -> DispatchResult {
1123 ensure_root(origin)?;
1124 Self::schedule_config_update(|config| {
1125 config.executor_params = new;
1126 })
1127 }
1128
1129 #[pallet::call_index(47)]
1131 #[pallet::weight((
1132 T::WeightInfo::set_config_with_balance(),
1133 DispatchClass::Operational,
1134 ))]
1135 pub fn set_on_demand_base_fee(origin: OriginFor<T>, new: Balance) -> DispatchResult {
1136 ensure_root(origin)?;
1137 Self::schedule_config_update(|config| {
1138 config.scheduler_params.on_demand_base_fee = new;
1139 })
1140 }
1141
1142 #[pallet::call_index(48)]
1144 #[pallet::weight((
1145 T::WeightInfo::set_config_with_perbill(),
1146 DispatchClass::Operational,
1147 ))]
1148 pub fn set_on_demand_fee_variability(origin: OriginFor<T>, new: Perbill) -> DispatchResult {
1149 ensure_root(origin)?;
1150 Self::schedule_config_update(|config| {
1151 config.scheduler_params.on_demand_fee_variability = new;
1152 })
1153 }
1154
1155 #[pallet::call_index(49)]
1157 #[pallet::weight((
1158 T::WeightInfo::set_config_with_option_u32(),
1159 DispatchClass::Operational,
1160 ))]
1161 pub fn set_on_demand_queue_max_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
1162 ensure_root(origin)?;
1163 Self::schedule_config_update(|config| {
1164 config.scheduler_params.on_demand_queue_max_size = new;
1165 })
1166 }
1167
1168 #[pallet::call_index(50)]
1170 #[pallet::weight((
1171 T::WeightInfo::set_config_with_perbill(),
1172 DispatchClass::Operational,
1173 ))]
1174 pub fn set_on_demand_target_queue_utilization(
1175 origin: OriginFor<T>,
1176 new: Perbill,
1177 ) -> DispatchResult {
1178 ensure_root(origin)?;
1179 Self::schedule_config_update(|config| {
1180 config.scheduler_params.on_demand_target_queue_utilization = new;
1181 })
1182 }
1183
1184 #[pallet::call_index(52)]
1188 #[pallet::weight((
1189 T::WeightInfo::set_config_with_u32(),
1190 DispatchClass::Operational
1191 ))]
1192 pub fn set_minimum_backing_votes(origin: OriginFor<T>, new: u32) -> DispatchResult {
1193 ensure_root(origin)?;
1194 Self::schedule_config_update(|config| {
1195 config.minimum_backing_votes = new;
1196 })
1197 }
1198
1199 #[pallet::call_index(53)]
1201 #[pallet::weight((
1202 T::WeightInfo::set_node_feature(),
1203 DispatchClass::Operational
1204 ))]
1205 pub fn set_node_feature(origin: OriginFor<T>, index: u8, value: bool) -> DispatchResult {
1206 ensure_root(origin)?;
1207
1208 Self::schedule_config_update(|config| {
1209 let index = usize::from(index);
1210 if config.node_features.len() <= index {
1211 config.node_features.resize(index + 1, false);
1212 }
1213 config.node_features.set(index, value);
1214 })
1215 }
1216
1217 #[pallet::call_index(54)]
1219 #[pallet::weight((
1220 T::WeightInfo::set_config_with_executor_params(),
1221 DispatchClass::Operational,
1222 ))]
1223 pub fn set_approval_voting_params(
1224 origin: OriginFor<T>,
1225 new: ApprovalVotingParams,
1226 ) -> DispatchResult {
1227 ensure_root(origin)?;
1228 Self::schedule_config_update(|config| {
1229 config.approval_voting_params = new;
1230 })
1231 }
1232
1233 #[pallet::call_index(55)]
1235 #[pallet::weight((
1236 T::WeightInfo::set_config_with_scheduler_params(),
1237 DispatchClass::Operational,
1238 ))]
1239 pub fn set_scheduler_params(
1240 origin: OriginFor<T>,
1241 new: SchedulerParams<BlockNumberFor<T>>,
1242 ) -> DispatchResult {
1243 ensure_root(origin)?;
1244 Self::schedule_config_update(|config| {
1245 config.scheduler_params = new;
1246 })
1247 }
1248 }
1249
1250 impl<T: Config> Pallet<T> {
1251 pub fn set_coretime_cores_unchecked(new: u32) -> DispatchResult {
1255 Self::schedule_config_update(|config| {
1256 config.scheduler_params.num_cores = new;
1257 })
1258 }
1259 }
1260
1261 #[pallet::hooks]
1262 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
1263 fn integrity_test() {
1264 assert_eq!(
1265 &ActiveConfig::<T>::hashed_key(),
1266 polkadot_primitives::well_known_keys::ACTIVE_CONFIG,
1267 "`well_known_keys::ACTIVE_CONFIG` doesn't match key of `ActiveConfig`! Make sure that the name of the\
1268 configuration pallet is `Configuration` in the runtime!",
1269 );
1270 }
1271 }
1272}
1273
1274pub struct SessionChangeOutcome<BlockNumber> {
1277 pub prev_config: HostConfiguration<BlockNumber>,
1279 pub new_config: Option<HostConfiguration<BlockNumber>>,
1281}
1282
1283impl<T: Config> Pallet<T> {
1284 pub(crate) fn initializer_initialize(_now: BlockNumberFor<T>) -> Weight {
1286 Weight::zero()
1287 }
1288
1289 pub(crate) fn initializer_finalize() {}
1291
1292 pub(crate) fn initializer_on_new_session(
1298 session_index: &SessionIndex,
1299 ) -> SessionChangeOutcome<BlockNumberFor<T>> {
1300 let pending_configs = PendingConfigs::<T>::get();
1301 let prev_config = ActiveConfig::<T>::get();
1302
1303 if pending_configs.is_empty() {
1305 return SessionChangeOutcome { prev_config, new_config: None }
1306 }
1307
1308 let (mut past_and_present, future) = pending_configs
1309 .into_iter()
1310 .partition::<Vec<_>, _>(|&(apply_at_session, _)| apply_at_session <= *session_index);
1311
1312 if past_and_present.len() > 1 {
1313 log::error!(
1316 target: LOG_TARGET,
1317 "Skipping applying configuration changes scheduled sessions in the past",
1318 );
1319 }
1320
1321 let new_config = past_and_present.pop().map(|(_, config)| config);
1322 if let Some(ref new_config) = new_config {
1323 ActiveConfig::<T>::put(new_config);
1325 }
1326
1327 PendingConfigs::<T>::put(future);
1328
1329 SessionChangeOutcome { prev_config, new_config }
1330 }
1331
1332 fn scheduled_session() -> SessionIndex {
1334 shared::Pallet::<T>::scheduled_session()
1335 }
1336
1337 pub fn force_set_active_config(config: HostConfiguration<BlockNumberFor<T>>) {
1341 ActiveConfig::<T>::set(config);
1342 }
1343
1344 #[inline(never)]
1362 pub(crate) fn schedule_config_update(
1363 updater: impl FnOnce(&mut HostConfiguration<BlockNumberFor<T>>),
1364 ) -> DispatchResult {
1365 let mut pending_configs = PendingConfigs::<T>::get();
1366
1367 let mut base_config = pending_configs
1394 .last()
1395 .map(|(_, config)| config.clone())
1396 .unwrap_or_else(ActiveConfig::<T>::get);
1397 let base_config_consistent = base_config.check_consistency().is_ok();
1398
1399 updater(&mut base_config);
1403 let new_config = base_config;
1404
1405 if BypassConsistencyCheck::<T>::get() {
1406 log::warn!(
1409 target: LOG_TARGET,
1410 "Bypassing the consistency check for the configuration change!",
1411 );
1412 } else if let Err(e) = new_config.check_consistency() {
1413 if base_config_consistent {
1414 log::warn!(
1418 target: LOG_TARGET,
1419 "Configuration change rejected due to invalid configuration: {:?}",
1420 e,
1421 );
1422 return Err(Error::<T>::InvalidNewValue.into())
1423 } else {
1424 log::warn!(
1430 target: LOG_TARGET,
1431 "The new configuration is broken but the old is broken as well. Proceeding",
1432 );
1433 }
1434 }
1435
1436 let scheduled_session = Self::scheduled_session();
1437
1438 if let Some(&mut (_, ref mut config)) = pending_configs
1439 .iter_mut()
1440 .find(|&&mut (apply_at_session, _)| apply_at_session >= scheduled_session)
1441 {
1442 *config = new_config;
1443 } else {
1444 pending_configs.push((scheduled_session, new_config));
1446 }
1447
1448 PendingConfigs::<T>::put(pending_configs);
1449
1450 Ok(())
1451 }
1452}
1453
1454pub struct ActiveConfigHrmpChannelSizeAndCapacityRatio<T, P>(core::marker::PhantomData<(T, P)>);
1457impl<T: crate::hrmp::pallet::Config, P: Get<Percent>> Get<(u32, u32)>
1458 for ActiveConfigHrmpChannelSizeAndCapacityRatio<T, P>
1459{
1460 fn get() -> (u32, u32) {
1461 let config = ActiveConfig::<T>::get();
1462 let percent = P::get();
1463 (percent * config.hrmp_channel_max_message_size, percent * config.hrmp_channel_max_capacity)
1464 }
1465}