configuration.rs 39.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

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

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

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

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

Shawn Tabrizi's avatar
Shawn Tabrizi committed
21
use crate::shared;
22
use frame_support::pallet_prelude::*;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
23
24
25
use frame_system::pallet_prelude::*;
use parity_scale_codec::{Decode, Encode};
use primitives::v1::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_POV_SIZE};
26
use sp_runtime::traits::Zero;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
27
use sp_std::prelude::*;
28

29
30
pub use pallet::*;

31
/// All configuration of the runtime with respect to parachains and parathreads.
32
#[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug)]
33
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
asynchronous rob's avatar
asynchronous rob committed
34
pub struct HostConfiguration<BlockNumber> {
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	// NOTE: This structure is used by parachains via merkle proofs. Therefore, this struct requires
	// special treatment.
	//
	// A parachain requested this struct can only depend on the subset of this struct. Specifically,
	// only a first few fields can be depended upon. These fields cannot be changed without
	// corresponding migration of the parachains.
	/**
	 * The parameters that are required for the parachains.
	 */

	/// The maximum validation code size, in bytes.
	pub max_code_size: u32,
	/// The maximum head-data size, in bytes.
	pub max_head_data_size: u32,
	/// Total number of individual messages allowed in the parachain -> relay-chain message queue.
	pub max_upward_queue_count: u32,
	/// Total size of messages allowed in the parachain -> relay-chain message queue before which
	/// no further messages may be added to it. If it exceeds this then the queue may contain only
	/// a single message.
	pub max_upward_queue_size: u32,
	/// The maximum size of an upward message that can be sent by a candidate.
	///
	/// This parameter affects the size upper bound of the `CandidateCommitments`.
	pub max_upward_message_size: u32,
	/// The maximum number of messages that a candidate can contain.
	///
	/// This parameter affects the size upper bound of the `CandidateCommitments`.
	pub max_upward_message_num_per_candidate: u32,
	/// The maximum number of outbound HRMP messages can be sent by a candidate.
	///
	/// This parameter affects the upper bound of size of `CandidateCommitments`.
	pub hrmp_max_message_num_per_candidate: u32,
67
68
69
70
	/// The minimum frequency at which parachains can update their validation code.
	pub validation_upgrade_frequency: BlockNumber,
	/// The delay, in blocks, before a validation upgrade is applied.
	pub validation_upgrade_delay: BlockNumber,
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

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

	/// The maximum POV block size, in bytes.
	pub max_pov_size: u32,
	/// The maximum size of a message that can be put in a downward message queue.
	///
	/// Since we require receiving at least one DMP message the obvious upper bound of the size is
	/// the PoV size. Of course, there is a lot of other different things that a parachain may
	/// decide to do with its PoV so this value in practice will be picked as a fraction of the PoV
	/// size.
	pub max_downward_message_size: u32,
	/// The amount of weight we wish to devote to the processing the dispatchable upward messages
	/// stage.
	///
	/// NOTE that this is a soft limit and could be exceeded.
89
	pub ump_service_total_weight: Weight,
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	/// The maximum number of outbound HRMP channels a parachain is allowed to open.
	pub hrmp_max_parachain_outbound_channels: u32,
	/// The maximum number of outbound HRMP channels a parathread is allowed to open.
	pub hrmp_max_parathread_outbound_channels: u32,
	/// Number of sessions after which an HRMP open channel request expires.
	pub hrmp_open_request_ttl: u32,
	/// The deposit that the sender should provide for opening an HRMP channel.
	pub hrmp_sender_deposit: Balance,
	/// The deposit that the recipient should provide for accepting opening an HRMP channel.
	pub hrmp_recipient_deposit: Balance,
	/// The maximum number of messages allowed in an HRMP channel at once.
	pub hrmp_channel_max_capacity: u32,
	/// The maximum total size of messages in bytes allowed in an HRMP channel at once.
	pub hrmp_channel_max_total_size: u32,
	/// The maximum number of inbound HRMP channels a parachain is allowed to accept.
	pub hrmp_max_parachain_inbound_channels: u32,
	/// The maximum number of inbound HRMP channels a parathread is allowed to accept.
	pub hrmp_max_parathread_inbound_channels: u32,
	/// The maximum size of a message that could ever be put into an HRMP channel.
	///
	/// This parameter affects the upper bound of size of `CandidateCommitments`.
	pub hrmp_channel_max_message_size: u32,

	/**
	 * Parameters that will unlikely be needed by parachains.
	 */

117
118
119
	/// How long to keep code on-chain, in blocks. This should be sufficiently long that disputes
	/// have concluded.
	pub code_retention_period: BlockNumber,
120
121
122
123
	/// The amount of execution cores to dedicate to parathread execution.
	pub parathread_cores: u32,
	/// The number of retries that a parathread author has to submit their block.
	pub parathread_retries: u32,
124
125
126
	/// How often parachain groups should be rotated across parachains.
	///
	/// Must be non-zero.
127
	pub group_rotation_frequency: BlockNumber,
128
129
	/// The availability period, in blocks, for parachains. This is the amount of blocks
	/// after inclusion that validators have to make the block available and signal its availability to
130
131
132
	/// the chain.
	///
	/// Must be at least 1.
133
134
	pub chain_availability_period: BlockNumber,
	/// The availability period, in blocks, for parathreads. Same as the `chain_availability_period`,
135
136
137
	/// but a differing timeout due to differing requirements.
	///
	/// Must be at least 1.
138
139
140
	pub thread_availability_period: BlockNumber,
	/// The amount of blocks ahead to schedule parachains and parathreads.
	pub scheduling_lookahead: u32,
141
142
143
	/// The maximum number of validators to have per core.
	///
	/// `None` means no maximum.
144
	pub max_validators_per_core: Option<u32>,
Denis_P's avatar
Denis_P committed
145
	/// The maximum number of validators to use for parachain consensus, period.
146
147
148
	///
	/// `None` means no maximum.
	pub max_validators: Option<u32>,
149
150
	/// The amount of sessions to keep for disputes.
	pub dispute_period: SessionIndex,
151
152
153
154
155
156
	/// How long after dispute conclusion to accept statements.
	pub dispute_post_conclusion_acceptance_period: BlockNumber,
	/// The maximum number of dispute spam slots
	pub dispute_max_spam_slots: u32,
	/// How long it takes for a dispute to conclude by time-out, if no supermajority is reached.
	pub dispute_conclusion_by_time_out_period: BlockNumber,
157
158
	/// The amount of consensus slots that must pass between submitting an assignment and
	/// submitting an approval vote before a validator is considered a no-show.
159
	///
160
161
162
163
164
165
166
167
168
	/// Must be at least 1.
	pub no_show_slots: u32,
	/// The number of delay tranches in total.
	pub n_delay_tranches: u32,
	/// The width of the zeroth delay tranche for approval assignments. This many delay tranches
	/// beyond 0 are all consolidated to form a wide 0 tranche.
	pub zeroth_delay_tranche_width: u32,
	/// The number of validators needed to approve a block.
	pub needed_approvals: u32,
Denis_P's avatar
Denis_P committed
169
	/// The number of samples to do of the `RelayVRFModulo` approval assignment criterion.
170
	pub relay_vrf_modulo_samples: u32,
171
172
}

173
174
175
176
177
178
179
180
181
impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber> {
	fn default() -> Self {
		Self {
			group_rotation_frequency: 1u32.into(),
			chain_availability_period: 1u32.into(),
			thread_availability_period: 1u32.into(),
			no_show_slots: 1u32.into(),
			validation_upgrade_frequency: Default::default(),
			validation_upgrade_delay: Default::default(),
182
			code_retention_period: Default::default(),
183
184
185
186
187
188
189
			max_code_size: Default::default(),
			max_pov_size: Default::default(),
			max_head_data_size: Default::default(),
			parathread_cores: Default::default(),
			parathread_retries: Default::default(),
			scheduling_lookahead: Default::default(),
			max_validators_per_core: Default::default(),
190
			max_validators: None,
191
192
193
194
			dispute_period: 6,
			dispute_post_conclusion_acceptance_period: 100.into(),
			dispute_max_spam_slots: 2,
			dispute_conclusion_by_time_out_period: 200.into(),
195
196
197
198
199
200
201
			n_delay_tranches: Default::default(),
			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(),
202
			ump_service_total_weight: Default::default(),
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
			max_upward_message_size: Default::default(),
			max_upward_message_num_per_candidate: Default::default(),
			hrmp_open_request_ttl: 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_max_parathread_inbound_channels: Default::default(),
			hrmp_channel_max_message_size: Default::default(),
			hrmp_max_parachain_outbound_channels: Default::default(),
			hrmp_max_parathread_outbound_channels: Default::default(),
			hrmp_max_message_num_per_candidate: Default::default(),
		}
	}
}

impl<BlockNumber: Zero> HostConfiguration<BlockNumber> {
	/// Checks that this instance is consistent with the requirements on each individual member.
	///
	/// # Panic
	///
	/// This function panics if any member is not set properly.
226
	pub fn check_consistency(&self) {
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
		if self.group_rotation_frequency.is_zero() {
			panic!("`group_rotation_frequency` must be non-zero!")
		}

		if self.chain_availability_period.is_zero() {
			panic!("`chain_availability_period` must be at least 1!")
		}

		if self.thread_availability_period.is_zero() {
			panic!("`thread_availability_period` must be at least 1!")
		}

		if self.no_show_slots.is_zero() {
			panic!("`no_show_slots` must be at least 1!")
		}
242
243
244
245

		if self.max_code_size > MAX_CODE_SIZE {
			panic!(
				"`max_code_size` ({}) is bigger than allowed by the client ({})",
Shawn Tabrizi's avatar
Shawn Tabrizi committed
246
				self.max_code_size, MAX_CODE_SIZE,
247
248
249
250
251
252
			)
		}

		if self.max_pov_size > MAX_POV_SIZE {
			panic!("`max_pov_size` is bigger than allowed by the client")
		}
253
254
255
	}
}

256
257
258
#[frame_support::pallet]
pub mod pallet {
	use super::*;
259

260
261
262
	#[pallet::pallet]
	#[pallet::generate_store(pub(super) trait Store)]
	pub struct Pallet<T>(_);
263

264
265
266
267
268
	#[pallet::config]
	pub trait Config: frame_system::Config + shared::Config {}

	#[pallet::error]
	pub enum Error<T> {
269
270
271
		/// The new value for a configuration parameter is invalid.
		InvalidNewValue,
	}
272

273
274
275
	/// The active configuration for the current session.
	#[pallet::storage]
	#[pallet::getter(fn config)]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
276
277
	pub(crate) type ActiveConfig<T: Config> =
		StorageValue<_, HostConfiguration<T::BlockNumber>, ValueQuery>;
278
279
280

	/// Pending configuration (if any) for the next session.
	#[pallet::storage]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
281
282
	pub(crate) type PendingConfig<T: Config> =
		StorageMap<_, Twox64Concat, SessionIndex, HostConfiguration<T::BlockNumber>>;
283
284
285

	#[pallet::genesis_config]
	pub struct GenesisConfig<T: Config> {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
286
		pub config: HostConfiguration<T::BlockNumber>,
287
288
289
290
291
	}

	#[cfg(feature = "std")]
	impl<T: Config> Default for GenesisConfig<T> {
		fn default() -> Self {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
292
			GenesisConfig { config: Default::default() }
293
294
295
296
297
298
299
300
301
302
		}
	}

	#[pallet::genesis_build]
	impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
		fn build(&self) {
			self.config.check_consistency();
			ActiveConfig::<T>::put(&self.config);
		}
	}
303

304
305
	#[pallet::call]
	impl<T: Config> Pallet<T> {
306
		/// Set the validation upgrade frequency.
307
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
308
309
310
311
		pub fn set_validation_upgrade_frequency(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
312
313
314
315
316
317
318
319
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.validation_upgrade_frequency, new) != new
			});
			Ok(())
		}

		/// Set the validation upgrade delay.
320
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
321
322
323
324
		pub fn set_validation_upgrade_delay(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
325
326
327
328
329
330
331
332
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.validation_upgrade_delay, new) != new
			});
			Ok(())
		}

		/// Set the acceptance period for an included candidate.
333
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
334
335
336
337
		pub fn set_code_retention_period(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
338
339
			ensure_root(origin)?;
			Self::update_config_member(|config| {
340
				sp_std::mem::replace(&mut config.code_retention_period, new) != new
341
342
343
344
345
			});
			Ok(())
		}

		/// Set the max validation code size for incoming upgrades.
346
347
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_code_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
348
			ensure_root(origin)?;
349
			ensure!(new <= MAX_CODE_SIZE, Error::<T>::InvalidNewValue);
350
351
352
353
354
355
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_code_size, new) != new
			});
			Ok(())
		}

356
		/// Set the max POV block size for incoming upgrades.
357
358
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_pov_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
359
			ensure_root(origin)?;
360
			ensure!(new <= MAX_POV_SIZE, Error::<T>::InvalidNewValue);
361
362
363
364
365
366
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_pov_size, new) != new
			});
			Ok(())
		}

367
		/// Set the max head data size for paras.
368
369
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_head_data_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
370
371
372
373
374
375
376
377
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_head_data_size, new) != new
			});
			Ok(())
		}

		/// Set the number of parathread execution cores.
378
379
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_parathread_cores(origin: OriginFor<T>, new: u32) -> DispatchResult {
380
381
382
383
384
385
386
387
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.parathread_cores, new) != new
			});
			Ok(())
		}

		/// Set the number of retries for a particular parathread.
388
389
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_parathread_retries(origin: OriginFor<T>, new: u32) -> DispatchResult {
390
391
392
393
394
395
396
397
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.parathread_retries, new) != new
			});
			Ok(())
		}

		/// Set the parachain validator-group rotation frequency
398
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
399
400
401
402
		pub fn set_group_rotation_frequency(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
403
			ensure_root(origin)?;
404
405
406

			ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);

407
			Self::update_config_member(|config| {
408
				sp_std::mem::replace(&mut config.group_rotation_frequency, new) != new
409
410
411
412
413
			});
			Ok(())
		}

		/// Set the availability period for parachains.
414
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
415
416
417
418
		pub fn set_chain_availability_period(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
419
			ensure_root(origin)?;
420
421
422

			ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);

423
424
425
426
427
428
429
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.chain_availability_period, new) != new
			});
			Ok(())
		}

		/// Set the availability period for parathreads.
430
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
431
432
433
434
		pub fn set_thread_availability_period(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
435
			ensure_root(origin)?;
436
437
438

			ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);

439
440
441
442
443
444
445
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.thread_availability_period, new) != new
			});
			Ok(())
		}

		/// Set the scheduling lookahead, in expected number of blocks at peak throughput.
446
447
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_scheduling_lookahead(origin: OriginFor<T>, new: u32) -> DispatchResult {
448
449
450
451
452
453
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.scheduling_lookahead, new) != new
			});
			Ok(())
		}
454

455
		/// Set the maximum number of validators to assign to any core.
456
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
457
458
459
460
		pub fn set_max_validators_per_core(
			origin: OriginFor<T>,
			new: Option<u32>,
		) -> DispatchResult {
461
462
463
464
465
466
467
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_validators_per_core, new) != new
			});
			Ok(())
		}

468
		/// Set the maximum number of validators to use in parachain consensus.
469
470
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_validators(origin: OriginFor<T>, new: Option<u32>) -> DispatchResult {
471
472
473
474
475
476
477
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_validators, new) != new
			});
			Ok(())
		}

478
		/// Set the dispute period, in number of sessions to keep for disputes.
479
480
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_dispute_period(origin: OriginFor<T>, new: SessionIndex) -> DispatchResult {
481
482
483
484
485
486
487
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.dispute_period, new) != new
			});
			Ok(())
		}

488
		/// Set the dispute post conclusion acceptance period.
489
		#[pallet::weight((1_000, DispatchClass::Operational))]
490
		pub fn set_dispute_post_conclusion_acceptance_period(
491
			origin: OriginFor<T>,
492
493
494
495
			new: T::BlockNumber,
		) -> DispatchResult {
			ensure_root(origin)?;
			Self::update_config_member(|config| {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
496
497
				sp_std::mem::replace(&mut config.dispute_post_conclusion_acceptance_period, new) !=
					new
498
499
500
501
502
			});
			Ok(())
		}

		/// Set the maximum number of dispute spam slots.
503
504
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_dispute_max_spam_slots(origin: OriginFor<T>, new: u32) -> DispatchResult {
505
506
507
508
509
510
511
512
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.dispute_max_spam_slots, new) != new
			});
			Ok(())
		}

		/// Set the dispute conclusion by time out period.
513
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
514
515
516
517
		pub fn set_dispute_conclusion_by_time_out_period(
			origin: OriginFor<T>,
			new: T::BlockNumber,
		) -> DispatchResult {
518
519
520
521
522
523
524
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.dispute_conclusion_by_time_out_period, new) != new
			});
			Ok(())
		}

525
526
		/// Set the no show slots, in number of number of consensus slots.
		/// Must be at least 1.
527
528
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_no_show_slots(origin: OriginFor<T>, new: u32) -> DispatchResult {
529
			ensure_root(origin)?;
530
531
532

			ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);

533
534
535
536
537
538
539
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.no_show_slots, new) != new
			});
			Ok(())
		}

		/// Set the total number of delay tranches.
540
541
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_n_delay_tranches(origin: OriginFor<T>, new: u32) -> DispatchResult {
542
543
544
545
546
547
548
549
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.n_delay_tranches, new) != new
			});
			Ok(())
		}

		/// Set the zeroth delay tranche width.
550
551
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_zeroth_delay_tranche_width(origin: OriginFor<T>, new: u32) -> DispatchResult {
552
553
554
555
556
557
558
559
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.zeroth_delay_tranche_width, new) != new
			});
			Ok(())
		}

		/// Set the number of validators needed to approve a block.
560
561
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_needed_approvals(origin: OriginFor<T>, new: u32) -> DispatchResult {
562
563
564
565
566
567
568
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.needed_approvals, new) != new
			});
			Ok(())
		}

Denis_P's avatar
Denis_P committed
569
		/// Set the number of samples to do of the `RelayVRFModulo` approval assignment criterion.
570
571
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_relay_vrf_modulo_samples(origin: OriginFor<T>, new: u32) -> DispatchResult {
572
573
574
575
576
577
578
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.relay_vrf_modulo_samples, new) != new
			});
			Ok(())
		}

579
		/// Sets the maximum items that can present in a upward dispatch queue at once.
580
581
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_upward_queue_count(origin: OriginFor<T>, new: u32) -> DispatchResult {
582
583
584
585
586
587
588
589
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_upward_queue_count, new) != new
			});
			Ok(())
		}

		/// Sets the maximum total size of items that can present in a upward dispatch queue at once.
590
591
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_upward_queue_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
592
593
594
595
596
597
598
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_upward_queue_size, new) != new
			});
			Ok(())
		}

599
		/// Set the critical downward message size.
600
601
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_downward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
602
603
604
605
606
607
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_downward_message_size, new) != new
			});
			Ok(())
		}
608
609

		/// Sets the soft limit for the phase of dispatching dispatchable upward messages.
610
611
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_ump_service_total_weight(origin: OriginFor<T>, new: Weight) -> DispatchResult {
612
613
			ensure_root(origin)?;
			Self::update_config_member(|config| {
614
				sp_std::mem::replace(&mut config.ump_service_total_weight, new) != new
615
616
617
618
619
			});
			Ok(())
		}

		/// Sets the maximum size of an upward message that can be sent by a candidate.
620
621
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_max_upward_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
622
623
624
625
626
627
628
629
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_upward_message_size, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of messages that a candidate can contain.
630
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
631
632
633
634
		pub fn set_max_upward_message_num_per_candidate(
			origin: OriginFor<T>,
			new: u32,
		) -> DispatchResult {
635
636
637
638
639
640
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.max_upward_message_num_per_candidate, new) != new
			});
			Ok(())
		}
Sergey Pepyakin's avatar
Sergey Pepyakin committed
641
642

		/// Sets the number of sessions after which an HRMP open channel request expires.
643
644
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_hrmp_open_request_ttl(origin: OriginFor<T>, new: u32) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
645
646
647
648
649
650
651
652
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_open_request_ttl, new) != new
			});
			Ok(())
		}

		/// Sets the amount of funds that the sender should provide for opening an HRMP channel.
653
654
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_hrmp_sender_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
655
656
657
658
659
660
661
662
663
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_sender_deposit, new) != new
			});
			Ok(())
		}

		/// Sets the amount of funds that the recipient should provide for accepting opening an HRMP
		/// channel.
664
665
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_hrmp_recipient_deposit(origin: OriginFor<T>, new: Balance) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
666
667
668
669
670
671
672
673
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_recipient_deposit, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of messages allowed in an HRMP channel at once.
674
675
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_hrmp_channel_max_capacity(origin: OriginFor<T>, new: u32) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
676
677
678
679
680
681
682
683
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_channel_max_capacity, new) != new
			});
			Ok(())
		}

		/// Sets the maximum total size of messages in bytes allowed in an HRMP channel at once.
684
685
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_hrmp_channel_max_total_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
686
687
688
689
690
691
692
693
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_channel_max_total_size, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of inbound HRMP channels a parachain is allowed to accept.
694
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
695
696
697
698
		pub fn set_hrmp_max_parachain_inbound_channels(
			origin: OriginFor<T>,
			new: u32,
		) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
699
700
701
702
703
704
705
706
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_max_parachain_inbound_channels, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of inbound HRMP channels a parathread is allowed to accept.
707
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
708
709
710
711
		pub fn set_hrmp_max_parathread_inbound_channels(
			origin: OriginFor<T>,
			new: u32,
		) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
712
713
714
715
716
717
718
719
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_max_parathread_inbound_channels, new) != new
			});
			Ok(())
		}

		/// Sets the maximum size of a message that could ever be put into an HRMP channel.
720
721
		#[pallet::weight((1_000, DispatchClass::Operational))]
		pub fn set_hrmp_channel_max_message_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
722
723
724
725
726
727
728
729
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_channel_max_message_size, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of outbound HRMP channels a parachain is allowed to open.
730
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
731
732
733
734
		pub fn set_hrmp_max_parachain_outbound_channels(
			origin: OriginFor<T>,
			new: u32,
		) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
735
736
737
738
739
740
741
742
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_max_parachain_outbound_channels, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of outbound HRMP channels a parathread is allowed to open.
743
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
744
745
746
747
		pub fn set_hrmp_max_parathread_outbound_channels(
			origin: OriginFor<T>,
			new: u32,
		) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
748
749
750
751
752
753
754
755
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_max_parathread_outbound_channels, new) != new
			});
			Ok(())
		}

		/// Sets the maximum number of outbound HRMP messages can be sent by a candidate.
756
		#[pallet::weight((1_000, DispatchClass::Operational))]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
757
758
759
760
		pub fn set_hrmp_max_message_num_per_candidate(
			origin: OriginFor<T>,
			new: u32,
		) -> DispatchResult {
Sergey Pepyakin's avatar
Sergey Pepyakin committed
761
762
763
764
765
766
			ensure_root(origin)?;
			Self::update_config_member(|config| {
				sp_std::mem::replace(&mut config.hrmp_max_message_num_per_candidate, new) != new
			});
			Ok(())
		}
767
	}
768
769
770
771
772
773
774
775
776
777
778
779

	#[pallet::hooks]
	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
		fn integrity_test() {
			assert_eq!(
				&ActiveConfig::<T>::hashed_key(),
				primitives::v1::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!",
			);
		}
	}
780
781
}

782
impl<T: Config> Pallet<T> {
783
784
785
786
787
788
	/// Called by the initializer to initialize the configuration module.
	pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight {
		0
	}

	/// Called by the initializer to finalize the configuration module.
Shawn Tabrizi's avatar
Shawn Tabrizi committed
789
	pub(crate) fn initializer_finalize() {}
790
791

	/// Called by the initializer to note that a new session has started.
Shawn Tabrizi's avatar
Shawn Tabrizi committed
792
	pub(crate) fn initializer_on_new_session(session_index: &SessionIndex) {
793
		if let Some(pending) = <Self as Store>::PendingConfig::take(session_index) {
794
			<Self as Store>::ActiveConfig::set(pending);
795
796
797
		}
	}

798
799
	/// Return the session index that should be used for any future scheduled changes.
	fn scheduled_session() -> SessionIndex {
800
		shared::Pallet::<T>::scheduled_session()
801
802
	}

803
804
805
806
807
808
809
	/// Forcibly set the active config. This should be used with extreme care, and typically
	/// only when enabling parachains runtime modules for the first time on a chain which has
	/// been running without them.
	pub fn force_set_active_config(config: HostConfiguration<T::BlockNumber>) {
		<Self as Store>::ActiveConfig::set(config);
	}

810
811
812
813
814
	// 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)]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
815
	fn update_config_member(updater: impl FnOnce(&mut HostConfiguration<T::BlockNumber>) -> bool) {
816
817
		let scheduled_session = Self::scheduled_session();
		let pending = <Self as Store>::PendingConfig::get(scheduled_session);
818
819
820
		let mut prev = pending.unwrap_or_else(Self::config);

		if updater(&mut prev) {
821
			<Self as Store>::PendingConfig::insert(scheduled_session, prev);
822
823
824
825
826
827
828
		}
	}
}

#[cfg(test)]
mod tests {
	use super::*;
829
	use crate::mock::{new_test_ext, Configuration, Origin};
830

831
	use frame_support::assert_ok;
832
833

	#[test]
834
	fn config_changes_after_2_session_boundary() {
835
836
837
838
839
840
		new_test_ext(Default::default()).execute_with(|| {
			let old_config = Configuration::config();
			let mut config = old_config.clone();
			config.validation_upgrade_delay = 100;
			assert!(old_config != config);

841
			assert_ok!(Configuration::set_validation_upgrade_delay(Origin::root(), 100));
842
843

			assert_eq!(Configuration::config(), old_config);
844
845
			assert_eq!(<Configuration as Store>::PendingConfig::get(1), None);

846
			Configuration::initializer_on_new_session(&1);
847

848
849
			assert_eq!(Configuration::config(), old_config);
			assert_eq!(<Configuration as Store>::PendingConfig::get(2), Some(config.clone()));
850

851
			Configuration::initializer_on_new_session(&2);
852
853

			assert_eq!(Configuration::config(), config);
854
			assert_eq!(<Configuration as Store>::PendingConfig::get(3), None);
855
856
857
858
859
860
861
862
863
		})
	}

	#[test]
	fn setting_pending_config_members() {
		new_test_ext(Default::default()).execute_with(|| {
			let new_config = HostConfiguration {
				validation_upgrade_frequency: 100,
				validation_upgrade_delay: 10,
864
				code_retention_period: 5,
865
				max_code_size: 100_000,
866
				max_pov_size: 1024,
867
868
869
				max_head_data_size: 1_000,
				parathread_cores: 2,
				parathread_retries: 5,
870
				group_rotation_frequency: 20,
871
872
873
				chain_availability_period: 10,
				thread_availability_period: 8,
				scheduling_lookahead: 3,
874
				max_validators_per_core: None,
875
				max_validators: None,
876
				dispute_period: 239,
877
878
879
				dispute_post_conclusion_acceptance_period: 10,
				dispute_max_spam_slots: 2,
				dispute_conclusion_by_time_out_period: 512,
880
881
882
883
884
				no_show_slots: 240,
				n_delay_tranches: 241,
				zeroth_delay_tranche_width: 242,
				needed_approvals: 242,
				relay_vrf_modulo_samples: 243,
885
886
				max_upward_queue_count: 1337,
				max_upward_queue_size: 228,
887
				max_downward_message_size: 2048,
888
				ump_service_total_weight: 20000,
889
890
				max_upward_message_size: 448,
				max_upward_message_num_per_candidate: 5,
Sergey Pepyakin's avatar
Sergey Pepyakin committed
891
892
893
894
895
896
897
898
899
900
901
				hrmp_open_request_ttl: 1312,
				hrmp_sender_deposit: 22,
				hrmp_recipient_deposit: 4905,
				hrmp_channel_max_capacity: 3921,
				hrmp_channel_max_total_size: 7687,
				hrmp_max_parachain_inbound_channels: 3722,
				hrmp_max_parathread_inbound_channels: 1967,
				hrmp_channel_max_message_size: 8192,
				hrmp_max_parachain_outbound_channels: 100,
				hrmp_max_parathread_outbound_channels: 200,
				hrmp_max_message_num_per_candidate: 20,
902
903
			};

904
			assert!(<Configuration as Store>::PendingConfig::get(shared::SESSION_DELAY).is_none());
905
906

			Configuration::set_validation_upgrade_frequency(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
907
908
909
910
				Origin::root(),
				new_config.validation_upgrade_frequency,
			)
			.unwrap();
911
			Configuration::set_validation_upgrade_delay(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
912
913
914
915
				Origin::root(),
				new_config.validation_upgrade_delay,
			)
			.unwrap();
916
			Configuration::set_code_retention_period(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
917
918
919
920
921
922
923
924
925
926
927
928
				Origin::root(),
				new_config.code_retention_period,
			)
			.unwrap();
			Configuration::set_max_code_size(Origin::root(), new_config.max_code_size).unwrap();
			Configuration::set_max_pov_size(Origin::root(), new_config.max_pov_size).unwrap();
			Configuration::set_max_head_data_size(Origin::root(), new_config.max_head_data_size)
				.unwrap();
			Configuration::set_parathread_cores(Origin::root(), new_config.parathread_cores)
				.unwrap();
			Configuration::set_parathread_retries(Origin::root(), new_config.parathread_retries)
				.unwrap();
929
			Configuration::set_group_rotation_frequency(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
930
931
932
933
				Origin::root(),
				new_config.group_rotation_frequency,
			)
			.unwrap();
934
			Configuration::set_chain_availability_period(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
935
936
937
938
				Origin::root(),
				new_config.chain_availability_period,
			)
			.unwrap();
939
			Configuration::set_thread_availability_period(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
940
941
942
943
				Origin::root(),
				new_config.thread_availability_period,
			)
			.unwrap();
944
			Configuration::set_scheduling_lookahead(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
945
946
947
948
				Origin::root(),
				new_config.scheduling_lookahead,
			)
			.unwrap();
949
			Configuration::set_max_validators_per_core(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
950
951
952
953
954
955
				Origin::root(),
				new_config.max_validators_per_core,
			)
			.unwrap();
			Configuration::set_max_validators(Origin::root(), new_config.max_validators).unwrap();
			Configuration::set_dispute_period(Origin::root(), new_config.dispute_period).unwrap();
956
			Configuration::set_dispute_post_conclusion_acceptance_period(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
957
958
959
960
				Origin::root(),
				new_config.dispute_post_conclusion_acceptance_period,
			)
			.unwrap();
961
			Configuration::set_dispute_max_spam_slots(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
962
963
964
965
				Origin::root(),
				new_config.dispute_max_spam_slots,
			)
			.unwrap();
966
			Configuration::set_dispute_conclusion_by_time_out_period(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
967
968
969
970
971
972
973
				Origin::root(),
				new_config.dispute_conclusion_by_time_out_period,
			)
			.unwrap();
			Configuration::set_no_show_slots(Origin::root(), new_config.no_show_slots).unwrap();
			Configuration::set_n_delay_tranches(Origin::root(), new_config.n_delay_tranches)
				.unwrap();
974
			Configuration::set_zeroth_delay_tranche_width(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
975
976
977
978
979
980
				Origin::root(),
				new_config.zeroth_delay_tranche_width,
			)
			.unwrap();
			Configuration::set_needed_approvals(Origin::root(), new_config.needed_approvals)
				.unwrap();
981
			Configuration::set_relay_vrf_modulo_samples(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
982
983
984
985
				Origin::root(),
				new_config.relay_vrf_modulo_samples,
			)
			.unwrap();
986
			Configuration::set_max_upward_queue_count(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
987
988
989
990
				Origin::root(),
				new_config.max_upward_queue_count,
			)
			.unwrap();
991
			Configuration::set_max_upward_queue_size(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
992
993
994
995
				Origin::root(),
				new_config.max_upward_queue_size,
			)
			.unwrap();
996
			Configuration::set_max_downward_message_size(
Shawn Tabrizi's avatar
Shawn Tabrizi committed
997
998
999
1000
				Origin::root(),
				new_config.max_downward_message_size,
			)
			.unwrap();
For faster browsing, not all history is shown. View entire blame