1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Polkadot.
3

            
4
// Polkadot is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Polkadot is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Configuration manager for the Polkadot runtime parachains logic.
18
//!
19
//! Configuration can change only at session boundaries and is buffered until then.
20

            
21
use crate::{inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND, shared};
22
use alloc::vec::Vec;
23
use codec::{Decode, Encode};
24
use frame_support::{pallet_prelude::*, DefaultNoBound};
25
use frame_system::pallet_prelude::*;
26
use polkadot_parachain_primitives::primitives::{
27
	MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM,
28
};
29
use polkadot_primitives::{
30
	ApprovalVotingParams, AsyncBackingParams, Balance, ExecutorParamError, ExecutorParams,
31
	NodeFeatures, SessionIndex, LEGACY_MIN_BACKING_VOTES, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE,
32
	MAX_POV_SIZE, ON_DEMAND_MAX_QUEUE_MAX_SIZE,
33
};
34
use sp_runtime::{traits::Zero, Perbill, Percent};
35

            
36
#[cfg(test)]
37
mod tests;
38

            
39
#[cfg(feature = "runtime-benchmarks")]
40
mod benchmarking;
41

            
42
pub mod migration;
43

            
44
pub use pallet::*;
45
use polkadot_primitives::vstaging::SchedulerParams;
46

            
47
const LOG_TARGET: &str = "runtime::configuration";
48

            
49
/// All configuration of the runtime with respect to paras.
50
#[derive(
51
	Clone,
52
	Encode,
53
	Decode,
54
	PartialEq,
55
	sp_core::RuntimeDebug,
56
	scale_info::TypeInfo,
57
	serde::Serialize,
58
	serde::Deserialize,
59
)]
60
#[serde(deny_unknown_fields)]
61
pub struct HostConfiguration<BlockNumber> {
62
	// NOTE: This structure is used by parachains via merkle proofs. Therefore, this struct
63
	// requires special treatment.
64
	//
65
	// A parachain requested this struct can only depend on the subset of this struct.
66
	// Specifically, only a first few fields can be depended upon. These fields cannot be changed
67
	// without corresponding migration of the parachains.
68
	/**
69
	 * The parameters that are required for the parachains.
70
	 */
71

            
72
	/// The maximum validation code size, in bytes.
73
	pub max_code_size: u32,
74
	/// The maximum head-data size, in bytes.
75
	pub max_head_data_size: u32,
76
	/// Total number of individual messages allowed in the parachain -> relay-chain message queue.
77
	pub max_upward_queue_count: u32,
78
	/// Total size of messages allowed in the parachain -> relay-chain message queue before which
79
	/// no further messages may be added to it. If it exceeds this then the queue may contain only
80
	/// a single message.
81
	pub max_upward_queue_size: u32,
82
	/// The maximum size of an upward message that can be sent by a candidate.
83
	///
84
	/// This parameter affects the size upper bound of the `CandidateCommitments`.
85
	pub max_upward_message_size: u32,
86
	/// The maximum number of messages that a candidate can contain.
87
	///
88
	/// This parameter affects the size upper bound of the `CandidateCommitments`.
89
	pub max_upward_message_num_per_candidate: u32,
90
	/// The maximum number of outbound HRMP messages can be sent by a candidate.
91
	///
92
	/// This parameter affects the upper bound of size of `CandidateCommitments`.
93
	pub hrmp_max_message_num_per_candidate: u32,
94
	/// The minimum period, in blocks, between which parachains can update their validation code.
95
	///
96
	/// This number is used to prevent parachains from spamming the relay chain with validation
97
	/// code upgrades. The only thing it controls is the number of blocks the
98
	/// `UpgradeRestrictionSignal` is set for the parachain in question.
99
	///
100
	/// If PVF pre-checking is enabled this should be greater than the maximum number of blocks
101
	/// PVF pre-checking can take. Intuitively, this number should be greater than the duration
102
	/// specified by [`pvf_voting_ttl`](Self::pvf_voting_ttl). Unlike,
103
	/// [`pvf_voting_ttl`](Self::pvf_voting_ttl), this parameter uses blocks as a unit.
104
	#[cfg_attr(feature = "std", serde(alias = "validation_upgrade_frequency"))]
105
	pub validation_upgrade_cooldown: BlockNumber,
106
	/// The delay, in blocks, after which an upgrade of the validation code is applied.
107
	///
108
	/// The upgrade for a parachain takes place when the first candidate which has relay-parent >=
109
	/// the relay-chain block where the upgrade is scheduled. This block is referred as to
110
	/// `expected_at`.
111
	///
112
	/// `expected_at` is determined when the upgrade is scheduled. This happens when the candidate
113
	/// that signals the upgrade is enacted. Right now, the relay-parent block number of the
114
	/// candidate scheduling the upgrade is used to determine the `expected_at`. This may change in
115
	/// the future with [#4601].
116
	///
117
	/// When PVF pre-checking is enabled, the upgrade is scheduled only after the PVF pre-check has
118
	/// been completed.
119
	///
120
	/// Note, there are situations in which `expected_at` in the past. For example, if
121
	/// [`paras_availability_period`](SchedulerParams::paras_availability_period) is less than the
122
	/// delay set by this field or if PVF pre-check took more time than the delay. In such cases,
123
	/// the upgrade is further at the earliest possible time determined by
124
	/// [`minimum_validation_upgrade_delay`](Self::minimum_validation_upgrade_delay).
125
	///
126
	/// The rationale for this delay has to do with relay-chain reversions. In case there is an
127
	/// invalid candidate produced with the new version of the code, then the relay-chain can
128
	/// revert [`validation_upgrade_delay`](Self::validation_upgrade_delay) many blocks back and
129
	/// still find the new code in the storage by hash.
130
	///
131
	/// [#4601]: https://github.com/paritytech/polkadot/issues/4601
132
	pub validation_upgrade_delay: BlockNumber,
133
	/// Asynchronous backing parameters.
134
	pub async_backing_params: AsyncBackingParams,
135

            
136
	/**
137
	 * The parameters that are not essential, but still may be of interest for parachains.
138
	 */
139

            
140
	/// The maximum POV block size, in bytes.
141
	pub max_pov_size: u32,
142
	/// The maximum size of a message that can be put in a downward message queue.
143
	///
144
	/// Since we require receiving at least one DMP message the obvious upper bound of the size is
145
	/// the PoV size. Of course, there is a lot of other different things that a parachain may
146
	/// decide to do with its PoV so this value in practice will be picked as a fraction of the PoV
147
	/// size.
148
	pub max_downward_message_size: u32,
149
	/// The maximum number of outbound HRMP channels a parachain is allowed to open.
150
	pub hrmp_max_parachain_outbound_channels: u32,
151
	/// The deposit that the sender should provide for opening an HRMP channel.
152
	pub hrmp_sender_deposit: Balance,
153
	/// The deposit that the recipient should provide for accepting opening an HRMP channel.
154
	pub hrmp_recipient_deposit: Balance,
155
	/// The maximum number of messages allowed in an HRMP channel at once.
156
	pub hrmp_channel_max_capacity: u32,
157
	/// The maximum total size of messages in bytes allowed in an HRMP channel at once.
158
	pub hrmp_channel_max_total_size: u32,
159
	/// The maximum number of inbound HRMP channels a parachain is allowed to accept.
160
	pub hrmp_max_parachain_inbound_channels: u32,
161
	/// The maximum size of a message that could ever be put into an HRMP channel.
162
	///
163
	/// This parameter affects the upper bound of size of `CandidateCommitments`.
164
	pub hrmp_channel_max_message_size: u32,
165
	/// The executor environment parameters
166
	pub executor_params: ExecutorParams,
167

            
168
	/**
169
	 * Parameters that will unlikely be needed by parachains.
170
	 */
171

            
172
	/// How long to keep code on-chain, in blocks. This should be sufficiently long that disputes
173
	/// have concluded.
174
	pub code_retention_period: BlockNumber,
175

            
176
	/// The maximum number of validators to use for parachain consensus, period.
177
	///
178
	/// `None` means no maximum.
179
	pub max_validators: Option<u32>,
180
	/// The amount of sessions to keep for disputes.
181
	pub dispute_period: SessionIndex,
182
	/// How long after dispute conclusion to accept statements.
183
	pub dispute_post_conclusion_acceptance_period: BlockNumber,
184
	/// The amount of consensus slots that must pass between submitting an assignment and
185
	/// submitting an approval vote before a validator is considered a no-show.
186
	///
187
	/// Must be at least 1.
188
	pub no_show_slots: u32,
189
	/// The number of delay tranches in total. Must be at least 1.
190
	pub n_delay_tranches: u32,
191
	/// The width of the zeroth delay tranche for approval assignments. This many delay tranches
192
	/// beyond 0 are all consolidated to form a wide 0 tranche.
193
	pub zeroth_delay_tranche_width: u32,
194
	/// The number of validators needed to approve a block.
195
	pub needed_approvals: u32,
196
	/// The number of samples to do of the `RelayVRFModulo` approval assignment criterion.
197
	pub relay_vrf_modulo_samples: u32,
198
	/// If an active PVF pre-checking vote observes this many number of sessions it gets
199
	/// automatically rejected.
200
	///
201
	/// 0 means PVF pre-checking will be rejected on the first observed session unless the voting
202
	/// gained supermajority before that the session change.
203
	pub pvf_voting_ttl: SessionIndex,
204
	/// The lower bound number of blocks an upgrade can be scheduled.
205
	///
206
	/// Typically, upgrade gets scheduled
207
	/// [`validation_upgrade_delay`](Self::validation_upgrade_delay) relay-chain blocks after
208
	/// the relay-parent of the parablock that signalled the validation code upgrade. However,
209
	/// in the case a pre-checking voting was concluded in a longer duration the upgrade will be
210
	/// scheduled to the next block.
211
	///
212
	/// That can disrupt parachain inclusion. Specifically, it will make the blocks that were
213
	/// already backed invalid.
214
	///
215
	/// To prevent that, we introduce the minimum number of blocks after which the upgrade can be
216
	/// scheduled. This number is controlled by this field.
217
	///
218
	/// This value should be greater than
219
	/// [`paras_availability_period`](SchedulerParams::paras_availability_period).
220
	pub minimum_validation_upgrade_delay: BlockNumber,
221
	/// The minimum number of valid backing statements required to consider a parachain candidate
222
	/// backable.
223
	pub minimum_backing_votes: u32,
224
	/// Node features enablement.
225
	pub node_features: NodeFeatures,
226
	/// Params used by approval-voting
227
	pub approval_voting_params: ApprovalVotingParams,
228
	/// Scheduler parameters
229
	pub scheduler_params: SchedulerParams<BlockNumber>,
230
}
231

            
232
impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber> {
233
24
	fn default() -> Self {
234
24
		let ret = Self {
235
24
			async_backing_params: AsyncBackingParams {
236
24
				max_candidate_depth: 0,
237
24
				allowed_ancestry_len: 0,
238
24
			},
239
24
			no_show_slots: 1u32.into(),
240
24
			validation_upgrade_cooldown: Default::default(),
241
24
			validation_upgrade_delay: 2u32.into(),
242
24
			code_retention_period: Default::default(),
243
24
			max_code_size: MAX_CODE_SIZE,
244
24
			max_pov_size: Default::default(),
245
24
			max_head_data_size: Default::default(),
246
24
			max_validators: None,
247
24
			dispute_period: 6,
248
24
			dispute_post_conclusion_acceptance_period: 100.into(),
249
24
			n_delay_tranches: 1,
250
24
			zeroth_delay_tranche_width: Default::default(),
251
24
			needed_approvals: Default::default(),
252
24
			relay_vrf_modulo_samples: Default::default(),
253
24
			max_upward_queue_count: Default::default(),
254
24
			max_upward_queue_size: Default::default(),
255
24
			max_downward_message_size: Default::default(),
256
24
			max_upward_message_size: Default::default(),
257
24
			max_upward_message_num_per_candidate: Default::default(),
258
24
			hrmp_sender_deposit: Default::default(),
259
24
			hrmp_recipient_deposit: Default::default(),
260
24
			hrmp_channel_max_capacity: Default::default(),
261
24
			hrmp_channel_max_total_size: Default::default(),
262
24
			hrmp_max_parachain_inbound_channels: Default::default(),
263
24
			hrmp_channel_max_message_size: Default::default(),
264
24
			hrmp_max_parachain_outbound_channels: Default::default(),
265
24
			hrmp_max_message_num_per_candidate: Default::default(),
266
24
			pvf_voting_ttl: 2u32.into(),
267
24
			minimum_validation_upgrade_delay: 2.into(),
268
24
			executor_params: Default::default(),
269
24
			approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 1 },
270
24
			minimum_backing_votes: LEGACY_MIN_BACKING_VOTES,
271
24
			node_features: NodeFeatures::EMPTY,
272
24
			scheduler_params: Default::default(),
273
24
		};
274
24

            
275
24
		#[cfg(feature = "runtime-benchmarks")]
276
24
		let ret = ret.with_benchmarking_default();
277
24
		ret
278
24
	}
279
}
280

            
281
#[cfg(feature = "runtime-benchmarks")]
282
impl<BlockNumber: Default + From<u32>> HostConfiguration<BlockNumber> {
283
	/// Mutate the values of self to be good estimates for benchmarking.
284
	///
285
	/// The values do not need to be worst-case, since the benchmarking logic extrapolates. They
286
	/// should be a bit more than usually expected.
287
	fn with_benchmarking_default(mut self) -> Self {
288
		self.max_head_data_size = self.max_head_data_size.max(1 << 20);
289
		self.max_downward_message_size = self.max_downward_message_size.max(1 << 16);
290
		self.hrmp_channel_max_capacity = self.hrmp_channel_max_capacity.max(1000);
291
		self.hrmp_channel_max_message_size = self.hrmp_channel_max_message_size.max(1 << 16);
292
		self.hrmp_max_parachain_inbound_channels =
293
			self.hrmp_max_parachain_inbound_channels.max(100);
294
		self.hrmp_max_parachain_outbound_channels =
295
			self.hrmp_max_parachain_outbound_channels.max(100);
296
		self
297
	}
298
}
299

            
300
/// Enumerates the possible inconsistencies of `HostConfiguration`.
301
#[derive(Debug)]
302
pub enum InconsistentError<BlockNumber> {
303
	/// `group_rotation_frequency` is set to zero.
304
	ZeroGroupRotationFrequency,
305
	/// `paras_availability_period` is set to zero.
306
	ZeroParasAvailabilityPeriod,
307
	/// `no_show_slots` is set to zero.
308
	ZeroNoShowSlots,
309
	/// `max_code_size` exceeds the hard limit of `MAX_CODE_SIZE`.
310
	MaxCodeSizeExceedHardLimit { max_code_size: u32 },
311
	/// `max_head_data_size` exceeds the hard limit of `MAX_HEAD_DATA_SIZE`.
312
	MaxHeadDataSizeExceedHardLimit { max_head_data_size: u32 },
313
	/// `max_pov_size` exceeds the hard limit of `MAX_POV_SIZE`.
314
	MaxPovSizeExceedHardLimit { max_pov_size: u32 },
315
	/// `minimum_validation_upgrade_delay` is less than `paras_availability_period`.
316
	MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod {
317
		minimum_validation_upgrade_delay: BlockNumber,
318
		paras_availability_period: BlockNumber,
319
	},
320
	/// `validation_upgrade_delay` is less than or equal 1.
321
	ValidationUpgradeDelayIsTooLow { validation_upgrade_delay: BlockNumber },
322
	/// Maximum UMP message size ([`MAX_UPWARD_MESSAGE_SIZE_BOUND`]) exceeded.
323
	MaxUpwardMessageSizeExceeded { max_message_size: u32 },
324
	/// Maximum HRMP message num ([`MAX_HORIZONTAL_MESSAGE_NUM`]) exceeded.
325
	MaxHorizontalMessageNumExceeded { max_message_num: u32 },
326
	/// Maximum UMP message num ([`MAX_UPWARD_MESSAGE_NUM`]) exceeded.
327
	MaxUpwardMessageNumExceeded { max_message_num: u32 },
328
	/// Maximum number of HRMP outbound channels exceeded.
329
	MaxHrmpOutboundChannelsExceeded,
330
	/// Maximum number of HRMP inbound channels exceeded.
331
	MaxHrmpInboundChannelsExceeded,
332
	/// `minimum_backing_votes` is set to zero.
333
	ZeroMinimumBackingVotes,
334
	/// `executor_params` are inconsistent.
335
	InconsistentExecutorParams { inner: ExecutorParamError },
336
	/// TTL should be bigger than lookahead
337
	LookaheadExceedsTTL,
338
	/// Lookahead is zero, while it must be at least 1 for parachains to work.
339
	LookaheadZero,
340
	/// Passed in queue size for on-demand was too large.
341
	OnDemandQueueSizeTooLarge,
342
	/// Number of delay tranches cannot be 0.
343
	ZeroDelayTranches,
344
}
345

            
346
impl<BlockNumber> HostConfiguration<BlockNumber>
347
where
348
	BlockNumber: Zero + PartialOrd + core::fmt::Debug + Clone + From<u32>,
349
{
350
	/// Checks that this instance is consistent with the requirements on each individual member.
351
	///
352
	/// # Errors
353
	///
354
	/// This function returns an error if the configuration is inconsistent.
355
3
	pub fn check_consistency(&self) -> Result<(), InconsistentError<BlockNumber>> {
356
		use InconsistentError::*;
357

            
358
3
		if self.scheduler_params.group_rotation_frequency.is_zero() {
359
			return Err(ZeroGroupRotationFrequency)
360
3
		}
361
3

            
362
3
		if self.scheduler_params.paras_availability_period.is_zero() {
363
			return Err(ZeroParasAvailabilityPeriod)
364
3
		}
365
3

            
366
3
		if self.no_show_slots.is_zero() {
367
			return Err(ZeroNoShowSlots)
368
3
		}
369
3

            
370
3
		if self.max_code_size > MAX_CODE_SIZE {
371
			return Err(MaxCodeSizeExceedHardLimit { max_code_size: self.max_code_size })
372
3
		}
373
3

            
374
3
		if self.max_head_data_size > MAX_HEAD_DATA_SIZE {
375
			return Err(MaxHeadDataSizeExceedHardLimit {
376
				max_head_data_size: self.max_head_data_size,
377
			})
378
3
		}
379
3

            
380
3
		if self.max_pov_size > MAX_POV_SIZE {
381
			return Err(MaxPovSizeExceedHardLimit { max_pov_size: self.max_pov_size })
382
3
		}
383
3

            
384
3
		if self.minimum_validation_upgrade_delay <= self.scheduler_params.paras_availability_period
385
		{
386
			return Err(MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod {
387
				minimum_validation_upgrade_delay: self.minimum_validation_upgrade_delay.clone(),
388
				paras_availability_period: self.scheduler_params.paras_availability_period.clone(),
389
			})
390
3
		}
391
3

            
392
3
		if self.validation_upgrade_delay <= 1.into() {
393
			return Err(ValidationUpgradeDelayIsTooLow {
394
				validation_upgrade_delay: self.validation_upgrade_delay.clone(),
395
			})
396
3
		}
397
3

            
398
3
		if self.max_upward_message_size > crate::inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND {
399
			return Err(MaxUpwardMessageSizeExceeded {
400
				max_message_size: self.max_upward_message_size,
401
			})
402
3
		}
403
3

            
404
3
		if self.hrmp_max_message_num_per_candidate > MAX_HORIZONTAL_MESSAGE_NUM {
405
			return Err(MaxHorizontalMessageNumExceeded {
406
				max_message_num: self.hrmp_max_message_num_per_candidate,
407
			})
408
3
		}
409
3

            
410
3
		if self.max_upward_message_num_per_candidate > MAX_UPWARD_MESSAGE_NUM {
411
			return Err(MaxUpwardMessageNumExceeded {
412
				max_message_num: self.max_upward_message_num_per_candidate,
413
			})
414
3
		}
415
3

            
416
3
		if self.hrmp_max_parachain_outbound_channels > crate::hrmp::HRMP_MAX_OUTBOUND_CHANNELS_BOUND
417
		{
418
			return Err(MaxHrmpOutboundChannelsExceeded)
419
3
		}
420
3

            
421
3
		if self.hrmp_max_parachain_inbound_channels > crate::hrmp::HRMP_MAX_INBOUND_CHANNELS_BOUND {
422
			return Err(MaxHrmpInboundChannelsExceeded)
423
3
		}
424
3

            
425
3
		if self.minimum_backing_votes.is_zero() {
426
			return Err(ZeroMinimumBackingVotes)
427
3
		}
428

            
429
3
		if let Err(inner) = self.executor_params.check_consistency() {
430
			return Err(InconsistentExecutorParams { inner })
431
3
		}
432
3

            
433
3
		if self.scheduler_params.ttl < self.scheduler_params.lookahead.into() {
434
			return Err(LookaheadExceedsTTL)
435
3
		}
436
3

            
437
3
		if self.scheduler_params.lookahead == 0 {
438
			return Err(LookaheadZero)
439
3
		}
440
3

            
441
3
		if self.scheduler_params.on_demand_queue_max_size > ON_DEMAND_MAX_QUEUE_MAX_SIZE {
442
			return Err(OnDemandQueueSizeTooLarge)
443
3
		}
444
3

            
445
3
		if self.n_delay_tranches.is_zero() {
446
			return Err(ZeroDelayTranches)
447
3
		}
448
3

            
449
3
		Ok(())
450
3
	}
451

            
452
	/// Checks that this instance is consistent with the requirements on each individual member.
453
	///
454
	/// # Panics
455
	///
456
	/// This function panics if the configuration is inconsistent.
457
3
	pub fn panic_if_not_consistent(&self) {
458
3
		if let Err(err) = self.check_consistency() {
459
			panic!("Host configuration is inconsistent: {:?}\nCfg:\n{:#?}", err, self);
460
3
		}
461
3
	}
462
}
463

            
464
pub trait WeightInfo {
465
	fn set_config_with_block_number() -> Weight;
466
	fn set_config_with_u32() -> Weight;
467
	fn set_config_with_option_u32() -> Weight;
468
	fn set_config_with_balance() -> Weight;
469
	fn set_hrmp_open_request_ttl() -> Weight;
470
	fn set_config_with_executor_params() -> Weight;
471
	fn set_config_with_perbill() -> Weight;
472
	fn set_node_feature() -> Weight;
473
	fn set_config_with_scheduler_params() -> Weight;
474
}
475

            
476
pub struct TestWeightInfo;
477
impl WeightInfo for TestWeightInfo {
478
	fn set_config_with_block_number() -> Weight {
479
		Weight::MAX
480
	}
481
	fn set_config_with_u32() -> Weight {
482
		Weight::MAX
483
	}
484
	fn set_config_with_option_u32() -> Weight {
485
		Weight::MAX
486
	}
487
	fn set_config_with_balance() -> Weight {
488
		Weight::MAX
489
	}
490
	fn set_hrmp_open_request_ttl() -> Weight {
491
		Weight::MAX
492
	}
493
	fn set_config_with_executor_params() -> Weight {
494
		Weight::MAX
495
	}
496
	fn set_config_with_perbill() -> Weight {
497
		Weight::MAX
498
	}
499
	fn set_node_feature() -> Weight {
500
		Weight::MAX
501
	}
502
	fn set_config_with_scheduler_params() -> Weight {
503
		Weight::MAX
504
	}
505
}
506

            
507
3548
#[frame_support::pallet]
508
pub mod pallet {
509
	use super::*;
510

            
511
	/// The in-code storage version.
512
	///
513
	/// v0-v1:  <https://github.com/paritytech/polkadot/pull/3575>
514
	/// v1-v2:  <https://github.com/paritytech/polkadot/pull/4420>
515
	/// v2-v3:  <https://github.com/paritytech/polkadot/pull/6091>
516
	/// v3-v4:  <https://github.com/paritytech/polkadot/pull/6345>
517
	/// v4-v5:  <https://github.com/paritytech/polkadot/pull/6937>
518
	///       + <https://github.com/paritytech/polkadot/pull/6961>
519
	///       + <https://github.com/paritytech/polkadot/pull/6934>
520
	/// v5-v6:  <https://github.com/paritytech/polkadot/pull/6271> (remove UMP dispatch queue)
521
	/// v6-v7:  <https://github.com/paritytech/polkadot/pull/7396>
522
	/// v7-v8:  <https://github.com/paritytech/polkadot/pull/6969>
523
	/// v8-v9:  <https://github.com/paritytech/polkadot/pull/7577>
524
	/// v9-v10: <https://github.com/paritytech/polkadot-sdk/pull/2177>
525
	/// v10-11: <https://github.com/paritytech/polkadot-sdk/pull/1191>
526
	/// v11-12: <https://github.com/paritytech/polkadot-sdk/pull/3181>
527
	const STORAGE_VERSION: StorageVersion = StorageVersion::new(12);
528

            
529
1698
	#[pallet::pallet]
530
	#[pallet::storage_version(STORAGE_VERSION)]
531
	#[pallet::without_storage_info]
532
	pub struct Pallet<T>(_);
533

            
534
	#[pallet::config]
535
	pub trait Config: frame_system::Config + shared::Config {
536
		/// Weight information for extrinsics in this pallet.
537
		type WeightInfo: WeightInfo;
538
	}
539

            
540
	#[pallet::error]
541
	pub enum Error<T> {
542
		/// The new value for a configuration parameter is invalid.
543
		InvalidNewValue,
544
	}
545

            
546
	/// The active configuration for the current session.
547
5551092
	#[pallet::storage]
548
	#[pallet::whitelist_storage]
549
	pub type ActiveConfig<T: Config> =
550
		StorageValue<_, HostConfiguration<BlockNumberFor<T>>, ValueQuery>;
551

            
552
	/// Pending configuration changes.
553
	///
554
	/// This is a list of configuration changes, each with a session index at which it should
555
	/// be applied.
556
	///
557
	/// The list is sorted ascending by session index. Also, this list can only contain at most
558
	/// 2 items: for the next session and for the `scheduled_session`.
559
540936
	#[pallet::storage]
560
	pub type PendingConfigs<T: Config> =
561
		StorageValue<_, Vec<(SessionIndex, HostConfiguration<BlockNumberFor<T>>)>, ValueQuery>;
562

            
563
	/// If this is set, then the configuration setters will bypass the consistency checks. This
564
	/// is meant to be used only as the last resort.
565
	#[pallet::storage]
566
	pub(crate) type BypassConsistencyCheck<T: Config> = StorageValue<_, bool, ValueQuery>;
567

            
568
	#[pallet::genesis_config]
569
	#[derive(DefaultNoBound)]
570
	pub struct GenesisConfig<T: Config> {
571
		pub config: HostConfiguration<BlockNumberFor<T>>,
572
	}
573

            
574
	#[pallet::genesis_build]
575
	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
576
3
		fn build(&self) {
577
3
			self.config.panic_if_not_consistent();
578
3
			ActiveConfig::<T>::put(&self.config);
579
3
		}
580
	}
581

            
582
25317
	#[pallet::call]
583
	impl<T: Config> Pallet<T> {
584
		/// Set the validation upgrade cooldown.
585
		#[pallet::call_index(0)]
586
		#[pallet::weight((
587
			T::WeightInfo::set_config_with_block_number(),
588
			DispatchClass::Operational,
589
		))]
590
		pub fn set_validation_upgrade_cooldown(
591
			origin: OriginFor<T>,
592
			new: BlockNumberFor<T>,
593
288
		) -> DispatchResult {
594
288
			ensure_root(origin)?;
595
			Self::schedule_config_update(|config| {
596
				config.validation_upgrade_cooldown = new;
597
			})
598
		}
599

            
600
		/// Set the validation upgrade delay.
601
		#[pallet::call_index(1)]
602
		#[pallet::weight((
603
			T::WeightInfo::set_config_with_block_number(),
604
			DispatchClass::Operational,
605
		))]
606
		pub fn set_validation_upgrade_delay(
607
			origin: OriginFor<T>,
608
			new: BlockNumberFor<T>,
609
90
		) -> DispatchResult {
610
90
			ensure_root(origin)?;
611
			Self::schedule_config_update(|config| {
612
				config.validation_upgrade_delay = new;
613
			})
614
		}
615

            
616
		/// Set the acceptance period for an included candidate.
617
		#[pallet::call_index(2)]
618
		#[pallet::weight((
619
			T::WeightInfo::set_config_with_block_number(),
620
			DispatchClass::Operational,
621
		))]
622
		pub fn set_code_retention_period(
623
			origin: OriginFor<T>,
624
			new: BlockNumberFor<T>,
625
30
		) -> DispatchResult {
626
30
			ensure_root(origin)?;
627
			Self::schedule_config_update(|config| {
628
				config.code_retention_period = new;
629
			})
630
		}
631

            
632
		/// Set the max validation code size for incoming upgrades.
633
		#[pallet::call_index(3)]
634
		#[pallet::weight((
635
			T::WeightInfo::set_config_with_u32(),
636
			DispatchClass::Operational,
637
		))]
638
162
		pub fn set_max_code_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
639
162
			ensure_root(origin)?;
640
			Self::schedule_config_update(|config| {
641
				config.max_code_size = new;
642
			})
643
		}
644

            
645
		/// Set the max POV block size for incoming upgrades.
646
		#[pallet::call_index(4)]
647
		#[pallet::weight((
648
			T::WeightInfo::set_config_with_u32(),
649
			DispatchClass::Operational,
650
		))]
651
81
		pub fn set_max_pov_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
652
81
			ensure_root(origin)?;
653
			Self::schedule_config_update(|config| {
654
				config.max_pov_size = new;
655
			})
656
		}
657

            
658
		/// Set the max head data size for paras.
659
		#[pallet::call_index(5)]
660
		#[pallet::weight((
661
			T::WeightInfo::set_config_with_u32(),
662
			DispatchClass::Operational,
663
		))]
664
81
		pub fn set_max_head_data_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
665
81
			ensure_root(origin)?;
666
			Self::schedule_config_update(|config| {
667
				config.max_head_data_size = new;
668
			})
669
		}
670

            
671
		/// Set the number of coretime execution cores.
672
		///
673
		/// NOTE: that this configuration is managed by the coretime chain. Only manually change
674
		/// this, if you really know what you are doing!
675
		#[pallet::call_index(6)]
676
		#[pallet::weight((
677
			T::WeightInfo::set_config_with_u32(),
678
			DispatchClass::Operational,
679
		))]
680
60
		pub fn set_coretime_cores(origin: OriginFor<T>, new: u32) -> DispatchResult {
681
60
			ensure_root(origin)?;
682
			Self::set_coretime_cores_unchecked(new)
683
		}
684

            
685
		/// Set the max number of times a claim may timeout on a core before it is abandoned
686
		#[pallet::call_index(7)]
687
		#[pallet::weight((
688
			T::WeightInfo::set_config_with_u32(),
689
			DispatchClass::Operational,
690
		))]
691
42
		pub fn set_max_availability_timeouts(origin: OriginFor<T>, new: u32) -> DispatchResult {
692
42
			ensure_root(origin)?;
693
			Self::schedule_config_update(|config| {
694
				config.scheduler_params.max_availability_timeouts = new;
695
			})
696
		}
697

            
698
		/// Set the parachain validator-group rotation frequency
699
		#[pallet::call_index(8)]
700
		#[pallet::weight((
701
			T::WeightInfo::set_config_with_block_number(),
702
			DispatchClass::Operational,
703
		))]
704
		pub fn set_group_rotation_frequency(
705
			origin: OriginFor<T>,
706
			new: BlockNumberFor<T>,
707
48
		) -> DispatchResult {
708
48
			ensure_root(origin)?;
709
			Self::schedule_config_update(|config| {
710
				config.scheduler_params.group_rotation_frequency = new;
711
			})
712
		}
713

            
714
		/// Set the availability period for paras.
715
		#[pallet::call_index(9)]
716
		#[pallet::weight((
717
			T::WeightInfo::set_config_with_block_number(),
718
			DispatchClass::Operational,
719
		))]
720
		pub fn set_paras_availability_period(
721
			origin: OriginFor<T>,
722
			new: BlockNumberFor<T>,
723
81
		) -> DispatchResult {
724
81
			ensure_root(origin)?;
725
			Self::schedule_config_update(|config| {
726
				config.scheduler_params.paras_availability_period = new;
727
			})
728
		}
729

            
730
		/// Set the scheduling lookahead, in expected number of blocks at peak throughput.
731
		#[pallet::call_index(11)]
732
		#[pallet::weight((
733
			T::WeightInfo::set_config_with_u32(),
734
			DispatchClass::Operational,
735
		))]
736
132
		pub fn set_scheduling_lookahead(origin: OriginFor<T>, new: u32) -> DispatchResult {
737
132
			ensure_root(origin)?;
738
			Self::schedule_config_update(|config| {
739
				config.scheduler_params.lookahead = new;
740
			})
741
		}
742

            
743
		/// Set the maximum number of validators to assign to any core.
744
		#[pallet::call_index(12)]
745
		#[pallet::weight((
746
			T::WeightInfo::set_config_with_option_u32(),
747
			DispatchClass::Operational,
748
		))]
749
		pub fn set_max_validators_per_core(
750
			origin: OriginFor<T>,
751
			new: Option<u32>,
752
33
		) -> DispatchResult {
753
33
			ensure_root(origin)?;
754
			Self::schedule_config_update(|config| {
755
				config.scheduler_params.max_validators_per_core = new;
756
			})
757
		}
758

            
759
		/// Set the maximum number of validators to use in parachain consensus.
760
		#[pallet::call_index(13)]
761
		#[pallet::weight((
762
			T::WeightInfo::set_config_with_option_u32(),
763
			DispatchClass::Operational,
764
		))]
765
105
		pub fn set_max_validators(origin: OriginFor<T>, new: Option<u32>) -> DispatchResult {
766
105
			ensure_root(origin)?;
767
			Self::schedule_config_update(|config| {
768
				config.max_validators = new;
769
			})
770
		}
771

            
772
		/// Set the dispute period, in number of sessions to keep for disputes.
773
		#[pallet::call_index(14)]
774
		#[pallet::weight((
775
			T::WeightInfo::set_config_with_u32(),
776
			DispatchClass::Operational,
777
		))]
778
18
		pub fn set_dispute_period(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
779
18
			ensure_root(origin)?;
780
			Self::schedule_config_update(|config| {
781
				config.dispute_period = new;
782
			})
783
		}
784

            
785
		/// Set the dispute post conclusion acceptance period.
786
		#[pallet::call_index(15)]
787
		#[pallet::weight((
788
			T::WeightInfo::set_config_with_block_number(),
789
			DispatchClass::Operational,
790
		))]
791
		pub fn set_dispute_post_conclusion_acceptance_period(
792
			origin: OriginFor<T>,
793
			new: BlockNumberFor<T>,
794
45
		) -> DispatchResult {
795
45
			ensure_root(origin)?;
796
			Self::schedule_config_update(|config| {
797
				config.dispute_post_conclusion_acceptance_period = new;
798
			})
799
		}
800

            
801
		/// Set the no show slots, in number of number of consensus slots.
802
		/// Must be at least 1.
803
		#[pallet::call_index(18)]
804
		#[pallet::weight((
805
			T::WeightInfo::set_config_with_u32(),
806
			DispatchClass::Operational,
807
		))]
808
51
		pub fn set_no_show_slots(origin: OriginFor<T>, new: u32) -> DispatchResult {
809
51
			ensure_root(origin)?;
810
			Self::schedule_config_update(|config| {
811
				config.no_show_slots = new;
812
			})
813
		}
814

            
815
		/// Set the total number of delay tranches.
816
		#[pallet::call_index(19)]
817
		#[pallet::weight((
818
			T::WeightInfo::set_config_with_u32(),
819
			DispatchClass::Operational,
820
		))]
821
27
		pub fn set_n_delay_tranches(origin: OriginFor<T>, new: u32) -> DispatchResult {
822
27
			ensure_root(origin)?;
823
			Self::schedule_config_update(|config| {
824
				config.n_delay_tranches = new;
825
			})
826
		}
827

            
828
		/// Set the zeroth delay tranche width.
829
		#[pallet::call_index(20)]
830
		#[pallet::weight((
831
			T::WeightInfo::set_config_with_u32(),
832
			DispatchClass::Operational,
833
		))]
834
30
		pub fn set_zeroth_delay_tranche_width(origin: OriginFor<T>, new: u32) -> DispatchResult {
835
30
			ensure_root(origin)?;
836
			Self::schedule_config_update(|config| {
837
				config.zeroth_delay_tranche_width = new;
838
			})
839
		}
840

            
841
		/// Set the number of validators needed to approve a block.
842
		#[pallet::call_index(21)]
843
		#[pallet::weight((
844
			T::WeightInfo::set_config_with_u32(),
845
			DispatchClass::Operational,
846
		))]
847
51
		pub fn set_needed_approvals(origin: OriginFor<T>, new: u32) -> DispatchResult {
848
51
			ensure_root(origin)?;
849
			Self::schedule_config_update(|config| {
850
				config.needed_approvals = new;
851
			})
852
		}
853

            
854
		/// Set the number of samples to do of the `RelayVRFModulo` approval assignment criterion.
855
		#[pallet::call_index(22)]
856
		#[pallet::weight((
857
			T::WeightInfo::set_config_with_u32(),
858
			DispatchClass::Operational,
859
		))]
860
195
		pub fn set_relay_vrf_modulo_samples(origin: OriginFor<T>, new: u32) -> DispatchResult {
861
195
			ensure_root(origin)?;
862
			Self::schedule_config_update(|config| {
863
				config.relay_vrf_modulo_samples = new;
864
			})
865
		}
866

            
867
		/// Sets the maximum items that can present in a upward dispatch queue at once.
868
		#[pallet::call_index(23)]
869
		#[pallet::weight((
870
			T::WeightInfo::set_config_with_u32(),
871
			DispatchClass::Operational,
872
		))]
873
48
		pub fn set_max_upward_queue_count(origin: OriginFor<T>, new: u32) -> DispatchResult {
874
48
			ensure_root(origin)?;
875
			Self::schedule_config_update(|config| {
876
				config.max_upward_queue_count = new;
877
			})
878
		}
879

            
880
		/// Sets the maximum total size of items that can present in a upward dispatch queue at
881
		/// once.
882
		#[pallet::call_index(24)]
883
		#[pallet::weight((
884
			T::WeightInfo::set_config_with_u32(),
885
			DispatchClass::Operational,
886
		))]
887
24
		pub fn set_max_upward_queue_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
888
24
			ensure_root(origin)?;
889
			ensure!(new <= MAX_UPWARD_MESSAGE_SIZE_BOUND, Error::<T>::InvalidNewValue);
890

            
891
			Self::schedule_config_update(|config| {
892
				config.max_upward_queue_size = new;
893
			})
894
		}
895

            
896
		/// Set the critical downward message size.
897
		#[pallet::call_index(25)]
898
		#[pallet::weight((
899
			T::WeightInfo::set_config_with_u32(),
900
			DispatchClass::Operational,
901
		))]
902
39
		pub fn set_max_downward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
903
39
			ensure_root(origin)?;
904
			Self::schedule_config_update(|config| {
905
				config.max_downward_message_size = new;
906
			})
907
		}
908

            
909
		/// Sets the maximum size of an upward message that can be sent by a candidate.
910
		#[pallet::call_index(27)]
911
		#[pallet::weight((
912
			T::WeightInfo::set_config_with_u32(),
913
			DispatchClass::Operational,
914
		))]
915
9
		pub fn set_max_upward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
916
9
			ensure_root(origin)?;
917
			Self::schedule_config_update(|config| {
918
				config.max_upward_message_size = new;
919
			})
920
		}
921

            
922
		/// Sets the maximum number of messages that a candidate can contain.
923
		#[pallet::call_index(28)]
924
		#[pallet::weight((
925
			T::WeightInfo::set_config_with_u32(),
926
			DispatchClass::Operational,
927
		))]
928
		pub fn set_max_upward_message_num_per_candidate(
929
			origin: OriginFor<T>,
930
			new: u32,
931
12
		) -> DispatchResult {
932
12
			ensure_root(origin)?;
933
			Self::schedule_config_update(|config| {
934
				config.max_upward_message_num_per_candidate = new;
935
			})
936
		}
937

            
938
		/// Sets the number of sessions after which an HRMP open channel request expires.
939
		#[pallet::call_index(29)]
940
		#[pallet::weight((
941
			T::WeightInfo::set_hrmp_open_request_ttl(),
942
			DispatchClass::Operational,
943
		))]
944
		// Deprecated, but is not marked as such, because that would trigger warnings coming from
945
		// the macro.
946
		pub fn set_hrmp_open_request_ttl(_origin: OriginFor<T>, _new: u32) -> DispatchResult {
947
			Err("this doesn't have any effect".into())
948
		}
949

            
950
		/// Sets the amount of funds that the sender should provide for opening an HRMP channel.
951
		#[pallet::call_index(30)]
952
		#[pallet::weight((
953
			T::WeightInfo::set_config_with_balance(),
954
			DispatchClass::Operational,
955
		))]
956
57
		pub fn set_hrmp_sender_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
957
57
			ensure_root(origin)?;
958
			Self::schedule_config_update(|config| {
959
				config.hrmp_sender_deposit = new;
960
			})
961
		}
962

            
963
		/// Sets the amount of funds that the recipient should provide for accepting opening an HRMP
964
		/// channel.
965
		#[pallet::call_index(31)]
966
		#[pallet::weight((
967
			T::WeightInfo::set_config_with_balance(),
968
			DispatchClass::Operational,
969
		))]
970
69
		pub fn set_hrmp_recipient_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
971
69
			ensure_root(origin)?;
972
			Self::schedule_config_update(|config| {
973
				config.hrmp_recipient_deposit = new;
974
			})
975
		}
976

            
977
		/// Sets the maximum number of messages allowed in an HRMP channel at once.
978
		#[pallet::call_index(32)]
979
		#[pallet::weight((
980
			T::WeightInfo::set_config_with_u32(),
981
			DispatchClass::Operational,
982
		))]
983
285
		pub fn set_hrmp_channel_max_capacity(origin: OriginFor<T>, new: u32) -> DispatchResult {
984
285
			ensure_root(origin)?;
985
			Self::schedule_config_update(|config| {
986
				config.hrmp_channel_max_capacity = new;
987
			})
988
		}
989

            
990
		/// Sets the maximum total size of messages in bytes allowed in an HRMP channel at once.
991
		#[pallet::call_index(33)]
992
		#[pallet::weight((
993
			T::WeightInfo::set_config_with_u32(),
994
			DispatchClass::Operational,
995
		))]
996
120
		pub fn set_hrmp_channel_max_total_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
997
120
			ensure_root(origin)?;
998
			Self::schedule_config_update(|config| {
999
				config.hrmp_channel_max_total_size = new;
			})
		}
		/// Sets the maximum number of inbound HRMP channels a parachain is allowed to accept.
		#[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,
54
		) -> DispatchResult {
54
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.hrmp_max_parachain_inbound_channels = new;
			})
		}
		/// Sets the maximum size of a message that could ever be put into an HRMP channel.
		#[pallet::call_index(36)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_u32(),
			DispatchClass::Operational,
		))]
153
		pub fn set_hrmp_channel_max_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
153
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.hrmp_channel_max_message_size = new;
			})
		}
		/// Sets the maximum number of outbound HRMP channels a parachain is allowed to open.
		#[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,
36
		) -> DispatchResult {
36
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.hrmp_max_parachain_outbound_channels = new;
			})
		}
		/// Sets the maximum number of outbound HRMP messages can be sent by a candidate.
		#[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,
6
		) -> DispatchResult {
6
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.hrmp_max_message_num_per_candidate = new;
			})
		}
		/// Set the number of session changes after which a PVF pre-checking voting is rejected.
		#[pallet::call_index(42)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_u32(),
			DispatchClass::Operational,
		))]
33
		pub fn set_pvf_voting_ttl(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
33
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.pvf_voting_ttl = new;
			})
		}
		/// Sets the minimum delay between announcing the upgrade block for a parachain until the
		/// upgrade taking place.
		///
		/// See the field documentation for information and constraints for the new value.
		#[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>,
30
		) -> DispatchResult {
30
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.minimum_validation_upgrade_delay = new;
			})
		}
		/// Setting this to true will disable consistency checks for the configuration setters.
		/// Use with caution.
		#[pallet::call_index(44)]
		#[pallet::weight((
			T::DbWeight::get().writes(1),
			DispatchClass::Operational,
		))]
27
		pub fn set_bypass_consistency_check(origin: OriginFor<T>, new: bool) -> DispatchResult {
27
			ensure_root(origin)?;
			BypassConsistencyCheck::<T>::put(new);
			Ok(())
		}
		/// Set the asynchronous backing parameters.
		#[pallet::call_index(45)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_option_u32(), // The same size in bytes.
			DispatchClass::Operational,
		))]
		pub fn set_async_backing_params(
			origin: OriginFor<T>,
			new: AsyncBackingParams,
42
		) -> DispatchResult {
42
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.async_backing_params = new;
			})
		}
		/// Set PVF executor parameters.
		#[pallet::call_index(46)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_executor_params(),
			DispatchClass::Operational,
		))]
108
		pub fn set_executor_params(origin: OriginFor<T>, new: ExecutorParams) -> DispatchResult {
108
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.executor_params = new;
			})
		}
		/// Set the on demand (parathreads) base fee.
		#[pallet::call_index(47)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_balance(),
			DispatchClass::Operational,
		))]
60
		pub fn set_on_demand_base_fee(origin: OriginFor<T>, new: Balance) -> DispatchResult {
60
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.scheduler_params.on_demand_base_fee = new;
			})
		}
		/// Set the on demand (parathreads) fee variability.
		#[pallet::call_index(48)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_perbill(),
			DispatchClass::Operational,
		))]
51
		pub fn set_on_demand_fee_variability(origin: OriginFor<T>, new: Perbill) -> DispatchResult {
51
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.scheduler_params.on_demand_fee_variability = new;
			})
		}
		/// Set the on demand (parathreads) queue max size.
		#[pallet::call_index(49)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_option_u32(),
			DispatchClass::Operational,
		))]
93
		pub fn set_on_demand_queue_max_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
93
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.scheduler_params.on_demand_queue_max_size = new;
			})
		}
		/// Set the on demand (parathreads) fee variability.
		#[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,
27
		) -> DispatchResult {
27
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.scheduler_params.on_demand_target_queue_utilization = new;
			})
		}
		/// Set the on demand (parathreads) ttl in the claimqueue.
		#[pallet::call_index(51)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_block_number(),
			DispatchClass::Operational
		))]
111
		pub fn set_on_demand_ttl(origin: OriginFor<T>, new: BlockNumberFor<T>) -> DispatchResult {
111
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.scheduler_params.ttl = new;
			})
		}
		/// Set the minimum backing votes threshold.
		#[pallet::call_index(52)]
		#[pallet::weight((
			T::WeightInfo::set_config_with_u32(),
			DispatchClass::Operational
		))]
69
		pub fn set_minimum_backing_votes(origin: OriginFor<T>, new: u32) -> DispatchResult {
69
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.minimum_backing_votes = new;
			})
		}
		/// Set/Unset a node feature.
		#[pallet::call_index(53)]
		#[pallet::weight((
			T::WeightInfo::set_node_feature(),
			DispatchClass::Operational
		))]
177
		pub fn set_node_feature(origin: OriginFor<T>, index: u8, value: bool) -> DispatchResult {
177
			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);
			})
		}
		/// Set approval-voting-params.
		#[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,
36
		) -> DispatchResult {
36
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.approval_voting_params = new;
			})
		}
		/// Set scheduler-params.
		#[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>>,
111
		) -> DispatchResult {
111
			ensure_root(origin)?;
			Self::schedule_config_update(|config| {
				config.scheduler_params = new;
			})
		}
	}
	impl<T: Config> Pallet<T> {
		/// Set coretime cores.
		///
		/// To be used if authorization is checked otherwise.
		pub fn set_coretime_cores_unchecked(new: u32) -> DispatchResult {
			Self::schedule_config_update(|config| {
				config.scheduler_params.num_cores = new;
			})
		}
	}
554367
	#[pallet::hooks]
	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
53637
		fn integrity_test() {
53637
			assert_eq!(
53637
				&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!",
			);
53637
		}
	}
}
/// A struct that holds the configuration that was active before the session change and optionally
/// a configuration that became active after the session change.
pub struct SessionChangeOutcome<BlockNumber> {
	/// Previously active configuration.
	pub prev_config: HostConfiguration<BlockNumber>,
	/// If new configuration was applied during the session change, this is the new configuration.
	pub new_config: Option<HostConfiguration<BlockNumber>>,
}
impl<T: Config> Pallet<T> {
	/// Called by the initializer to initialize the configuration pallet.
194763
	pub(crate) fn initializer_initialize(_now: BlockNumberFor<T>) -> Weight {
194763
		Weight::zero()
194763
	}
	/// Called by the initializer to finalize the configuration pallet.
194763
	pub(crate) fn initializer_finalize() {}
	/// Called by the initializer to note that a new session has started.
	///
	/// Returns the configuration that was actual before the session change and the configuration
	/// that became active after the session change. If there were no scheduled changes, both will
	/// be the same.
135234
	pub(crate) fn initializer_on_new_session(
135234
		session_index: &SessionIndex,
135234
	) -> SessionChangeOutcome<BlockNumberFor<T>> {
135234
		let pending_configs = PendingConfigs::<T>::get();
135234
		let prev_config = ActiveConfig::<T>::get();
135234

            
135234
		// No pending configuration changes, so we're done.
135234
		if pending_configs.is_empty() {
135234
			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 {
			// This should never happen since we schedule configuration changes only into the future
			// sessions and this handler called for each session change.
			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 {
			// Apply the new configuration.
			ActiveConfig::<T>::put(new_config);
		}
		PendingConfigs::<T>::put(future);
		SessionChangeOutcome { prev_config, new_config }
135234
	}
	/// Return the session index that should be used for any future scheduled changes.
	fn scheduled_session() -> SessionIndex {
		shared::Pallet::<T>::scheduled_session()
	}
	/// Forcibly set the active config. This should be used with extreme care, and typically
	/// only when enabling parachains runtime pallets for the first time on a chain which has
	/// been running without them.
	pub fn force_set_active_config(config: HostConfiguration<BlockNumberFor<T>>) {
		ActiveConfig::<T>::set(config);
	}
	/// This function should be used to update members of the configuration.
	///
	/// This function is used to update the configuration in a way that is safe. It will check the
	/// resulting configuration and ensure that the update is valid. If the update is invalid, it
	/// will check if the previous configuration was valid. If it was invalid, we proceed with
	/// updating the configuration, giving a chance to recover from such a condition.
	///
	/// The actual configuration change take place after a couple of sessions have passed. In case
	/// this function is called more than once in a session, then the pending configuration change
	/// will be updated and the changes will be applied at once.
	// NOTE: Explicitly tell rustc not to inline this because otherwise heuristics note the incoming
	// closure making it's attractive to inline. However, in this case, we will end up with lots of
	// duplicated code (making this function to show up in the top of heaviest functions) only for
	// the sake of essentially avoiding an indirect call. Doesn't worth it.
	#[inline(never)]
	pub(crate) fn schedule_config_update(
		updater: impl FnOnce(&mut HostConfiguration<BlockNumberFor<T>>),
	) -> DispatchResult {
		let mut pending_configs = PendingConfigs::<T>::get();
		// 1. pending_configs = [] No pending configuration changes.
		//
		//    That means we should use the active config as the base configuration. We will insert
		//    the new pending configuration as (cur+2, new_config) into the list.
		//
		// 2. pending_configs = [(cur+2, X)] There is a configuration that is pending for the
		//    scheduled session.
		//
		//    We will use X as the base configuration. We can update the pending configuration X
		//    directly.
		//
		// 3. pending_configs = [(cur+1, X)] There is a pending configuration scheduled and it will
		//    be applied in the next session.
		//
		//    We will use X as the base configuration. We need to schedule a new configuration
		// change    for the `scheduled_session` and use X as the base for the new configuration.
		//
		// 4. pending_configs = [(cur+1, X), (cur+2, Y)] There is a pending configuration change in
		//    the next session and for the scheduled session. Due to case №3, we can be sure that Y
		//    is based on top of X. This means we can use Y as the base configuration and update Y
		//    directly.
		//
		// There cannot be (cur, X) because those are applied in the session change handler for the
		// current session.
		// First, we need to decide what we should use as the base configuration.
		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();
		// Now, we need to decide what the new configuration should be.
		// We also move the `base_config` to `new_config` to emphasize that the base config was
		// destroyed by the `updater`.
		updater(&mut base_config);
		let new_config = base_config;
		if BypassConsistencyCheck::<T>::get() {
			// This will emit a warning each configuration update if the consistency check is
			// bypassed. This is an attempt to make sure the bypass is not accidentally left on.
			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 {
				// Base configuration is consistent and the new configuration is inconsistent.
				// This means that the value set by the `updater` is invalid and we can return
				// it as an error.
				log::warn!(
					target: LOG_TARGET,
					"Configuration change rejected due to invalid configuration: {:?}",
					e,
				);
				return Err(Error::<T>::InvalidNewValue.into())
			} else {
				// The configuration was already broken, so we can as well proceed with the update.
				// You cannot break something that is already broken.
				//
				// That will allow to call several functions and ultimately return the configuration
				// into consistent state.
				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 {
			// We are scheduling a new configuration change for the scheduled session.
			pending_configs.push((scheduled_session, new_config));
		}
		PendingConfigs::<T>::put(pending_configs);
		Ok(())
	}
}
/// The implementation of `Get<(u32, u32)>` which reads `ActiveConfig` and returns `P` percent of
/// `hrmp_channel_max_message_size` / `hrmp_channel_max_capacity`.
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)
	}
}