Skip to main content

glutton_westend_runtime/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! # Glutton Westend Runtime
17//!
18//! The purpose of the Glutton parachain is to do stress testing on the Kusama
19//! network. This runtime targets the Westend runtime to allow development
20//! separate to the Kusama runtime.
21//!
22//! There may be multiple instances of the Glutton parachain deployed and
23//! connected to its parent relay chain.
24//!
25//! These parachains are not holding any real value. Their purpose is to stress
26//! test the network.
27//!
28//! ### Governance
29//!
30//! Glutton defers its governance (namely, its `Root` origin), to its Relay
31//! Chain parent, Kusama (or Westend for development purposes).
32//!
33//! ### XCM
34//!
35//! Since the main goal of Glutton is solely stress testing, the parachain will
36//! only be able receive XCM messages from the Relay Chain via DMP. This way the
37//! Glutton parachains will be able to listen for upgrades that are coming from
38//! the Relay chain.
39
40#![cfg_attr(not(feature = "std"), no_std)]
41#![recursion_limit = "256"]
42
43// Make the WASM binary available.
44#[cfg(feature = "std")]
45include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
46
47pub mod genesis_config_presets;
48pub mod weights;
49pub mod xcm_config;
50
51extern crate alloc;
52
53use alloc::{vec, vec::Vec};
54use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
55use sp_api::impl_runtime_apis;
56pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
57use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
58use sp_runtime::{
59	generic, impl_opaque_keys,
60	traits::{BlakeTwo256, Block as BlockT},
61	transaction_validity::{TransactionSource, TransactionValidity},
62	ApplyExtrinsicResult,
63};
64use sp_session::OpaqueGeneratedSessionKeys;
65#[cfg(feature = "std")]
66use sp_version::NativeVersion;
67use sp_version::RuntimeVersion;
68
69use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
70pub use frame_support::{
71	construct_runtime, derive_impl,
72	dispatch::DispatchClass,
73	genesis_builder_helper::{build_state, get_preset},
74	parameter_types,
75	traits::{
76		ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, IsInVec, Randomness,
77	},
78	weights::{
79		constants::{
80			BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND,
81		},
82		IdentityFee, Weight,
83	},
84	PalletId, StorageValue,
85};
86use frame_system::{
87	limits::{BlockLength, BlockWeights},
88	EnsureRoot,
89};
90use parachains_common::{AccountId, Signature};
91#[cfg(any(feature = "std", test))]
92pub use sp_runtime::BuildStorage;
93pub use sp_runtime::{Perbill, Permill};
94use testnet_parachains_constants::westend::consensus::*;
95
96impl_opaque_keys! {
97	pub struct SessionKeys {
98		pub aura: Aura,
99	}
100}
101
102#[sp_version::runtime_version]
103pub const VERSION: RuntimeVersion = RuntimeVersion {
104	spec_name: alloc::borrow::Cow::Borrowed("glutton-westend"),
105	impl_name: alloc::borrow::Cow::Borrowed("glutton-westend"),
106	authoring_version: 1,
107	spec_version: 1_022_003,
108	impl_version: 0,
109	apis: RUNTIME_API_VERSIONS,
110	transaction_version: 1,
111	system_version: 1,
112};
113
114/// The version information used to identify this runtime when compiled natively.
115#[cfg(feature = "std")]
116pub fn native_version() -> NativeVersion {
117	NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
118}
119
120/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
121/// This is used to limit the maximal weight of a single extrinsic.
122const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
123/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
124/// by  Operational  extrinsics.
125const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
126
127parameter_types! {
128	pub const BlockHashCount: BlockNumber = 4096;
129	pub const Version: RuntimeVersion = VERSION;
130	pub RuntimeBlockLength: BlockLength = BlockLength::builder()
131		.max_length(5 * 1024 * 1024)
132		.modify_max_length_for_class(DispatchClass::Normal, |m| {
133			*m = NORMAL_DISPATCH_RATIO * *m
134		})
135		.build();
136	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
137		.base_block(BlockExecutionWeight::get())
138		.for_class(DispatchClass::all(), |weights| {
139			weights.base_extrinsic = ExtrinsicBaseWeight::get();
140		})
141		.for_class(DispatchClass::Normal, |weights| {
142			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
143		})
144		.for_class(DispatchClass::Operational, |weights| {
145			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
146			// Operational transactions have some extra reserved space, so that they
147			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
148			weights.reserved = Some(
149				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
150			);
151		})
152		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
153		.build_or_panic();
154	pub const SS58Prefix: u8 = 42;
155}
156
157#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)]
158impl frame_system::Config for Runtime {
159	type AccountId = AccountId;
160	type Nonce = Nonce;
161	type Hash = Hash;
162	type Block = Block;
163	type BlockHashCount = BlockHashCount;
164	type Version = Version;
165	type BlockWeights = RuntimeBlockWeights;
166	type BlockLength = RuntimeBlockLength;
167	type SS58Prefix = SS58Prefix;
168	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
169	type MaxConsumers = frame_support::traits::ConstU32<16>;
170}
171
172parameter_types! {
173	// We do anything the parent chain tells us in this runtime.
174	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(2);
175	pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
176}
177
178/// Build with an offset of 1 behind the relay chain.
179const RELAY_PARENT_OFFSET: u32 = 1;
180
181/// The upper limit of how many parachain blocks are processed by the relay chain per
182/// parent. Limits the number of blocks authored per slot. This determines the minimum
183/// block time of the parachain:
184/// `RELAY_CHAIN_SLOT_DURATION_MILLIS/BLOCK_PROCESSING_VELOCITY`
185const BLOCK_PROCESSING_VELOCITY: u32 = 3;
186
187/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included
188/// into the relay chain.
189const UNINCLUDED_SEGMENT_CAPACITY: u32 = (3 + RELAY_PARENT_OFFSET) * BLOCK_PROCESSING_VELOCITY;
190
191type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook<
192	Runtime,
193	RELAY_CHAIN_SLOT_DURATION_MILLIS,
194	BLOCK_PROCESSING_VELOCITY,
195	UNINCLUDED_SEGMENT_CAPACITY,
196>;
197
198impl cumulus_pallet_parachain_system::Config for Runtime {
199	type RuntimeEvent = RuntimeEvent;
200	type OnSystemEvent = ();
201	type SelfParaId = parachain_info::Pallet<Runtime>;
202	type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
203	type OutboundXcmpMessageSource = ();
204	type ReservedDmpWeight = ReservedDmpWeight;
205	type XcmpMessageHandler = ();
206	type ReservedXcmpWeight = ();
207	type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases;
208	type ConsensusHook = ConsensusHook;
209	type WeightInfo = weights::cumulus_pallet_parachain_system::WeightInfo<Runtime>;
210	type RelayParentOffset = ConstU32<RELAY_PARENT_OFFSET>;
211}
212
213parameter_types! {
214	pub MessageQueueServiceWeight: Weight = Perbill::from_percent(80) *
215		RuntimeBlockWeights::get().max_block;
216}
217
218impl pallet_message_queue::Config for Runtime {
219	type RuntimeEvent = RuntimeEvent;
220	type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
221	#[cfg(feature = "runtime-benchmarks")]
222	type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
223		cumulus_primitives_core::AggregateMessageOrigin,
224	>;
225	#[cfg(not(feature = "runtime-benchmarks"))]
226	type MessageProcessor = xcm_builder::ProcessXcmMessage<
227		AggregateMessageOrigin,
228		xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
229		RuntimeCall,
230	>;
231	type Size = u32;
232	type QueueChangeHandler = ();
233	// No XCMP queue pallet deployed.
234	type QueuePausedQuery = ();
235	type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>;
236	type MaxStale = sp_core::ConstU32<8>;
237	type ServiceWeight = MessageQueueServiceWeight;
238	type IdleMaxServiceWeight = MessageQueueServiceWeight;
239}
240
241impl parachain_info::Config for Runtime {}
242
243impl cumulus_pallet_aura_ext::Config for Runtime {}
244
245impl pallet_timestamp::Config for Runtime {
246	type Moment = u64;
247	type OnTimestampSet = Aura;
248	type MinimumPeriod = ConstU64<0>;
249	type WeightInfo = weights::pallet_timestamp::WeightInfo<Runtime>;
250}
251
252impl pallet_aura::Config for Runtime {
253	type AuthorityId = AuraId;
254	type DisabledValidators = ();
255	type MaxAuthorities = ConstU32<100_000>;
256	type AllowMultipleBlocksPerSlot = ConstBool<true>;
257	type SlotDuration = ConstU64<SLOT_DURATION>;
258}
259
260impl pallet_glutton::Config for Runtime {
261	type RuntimeEvent = RuntimeEvent;
262	type WeightInfo = weights::pallet_glutton::WeightInfo<Runtime>;
263	type AdminOrigin = EnsureRoot<AccountId>;
264}
265
266impl pallet_sudo::Config for Runtime {
267	type RuntimeEvent = RuntimeEvent;
268	type RuntimeCall = RuntimeCall;
269	type WeightInfo = ();
270}
271
272construct_runtime! {
273	pub enum Runtime
274	{
275		System: frame_system = 0,
276		ParachainSystem: cumulus_pallet_parachain_system = 1,
277		ParachainInfo: parachain_info = 2,
278		Timestamp: pallet_timestamp = 3,
279
280		// DMP handler.
281		CumulusXcm: cumulus_pallet_xcm = 10,
282		MessageQueue: pallet_message_queue = 11,
283
284		// The main stage.
285		Glutton: pallet_glutton = 20,
286
287		// Collator support
288		Aura: pallet_aura = 30,
289		AuraExt: cumulus_pallet_aura_ext = 31,
290
291		// Sudo.
292		Sudo: pallet_sudo = 255,
293	}
294}
295
296/// Index of a transaction in the chain.
297pub type Nonce = u32;
298/// A hash of some data used by the chain.
299pub type Hash = sp_core::H256;
300/// An index to a block.
301pub type BlockNumber = u32;
302/// The address format for describing accounts.
303pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
304/// Block header type as expected by this runtime.
305pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
306/// Block type as expected by this runtime.
307pub type Block = generic::Block<Header, UncheckedExtrinsic>;
308/// A Block signed with a Justification
309pub type SignedBlock = generic::SignedBlock<Block>;
310/// BlockId type as expected by this runtime.
311pub type BlockId = generic::BlockId<Block>;
312/// The extension to the basic transaction logic.
313pub type TxExtension = (
314	frame_system::AuthorizeCall<Runtime>,
315	pallet_sudo::CheckOnlySudoAccount<Runtime>,
316	frame_system::CheckNonZeroSender<Runtime>,
317	frame_system::CheckSpecVersion<Runtime>,
318	frame_system::CheckTxVersion<Runtime>,
319	frame_system::CheckGenesis<Runtime>,
320	frame_system::CheckEra<Runtime>,
321	frame_system::CheckWeight<Runtime>,
322	frame_system::WeightReclaim<Runtime>,
323);
324/// Unchecked extrinsic type as expected by this runtime.
325pub type UncheckedExtrinsic =
326	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
327/// Executive: handles dispatch to the various modules.
328pub type Executive = frame_executive::Executive<
329	Runtime,
330	Block,
331	frame_system::ChainContext<Runtime>,
332	Runtime,
333	AllPalletsWithSystem,
334>;
335
336#[cfg(feature = "runtime-benchmarks")]
337mod benches {
338	frame_benchmarking::define_benchmarks!(
339		[cumulus_pallet_parachain_system, ParachainSystem]
340		[frame_system, SystemBench::<Runtime>]
341		[frame_system_extensions, SystemExtensionsBench::<Runtime>]
342		[pallet_glutton, Glutton]
343		[pallet_message_queue, MessageQueue]
344		[pallet_timestamp, Timestamp]
345	);
346}
347
348impl_runtime_apis! {
349	impl sp_api::Core<Block> for Runtime {
350		fn version() -> RuntimeVersion {
351			VERSION
352		}
353
354		fn execute_block(block: <Block as BlockT>::LazyBlock) {
355			Executive::execute_block(block)
356		}
357
358		fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
359			Executive::initialize_block(header)
360		}
361	}
362
363	impl sp_api::Metadata<Block> for Runtime {
364		fn metadata() -> OpaqueMetadata {
365			OpaqueMetadata::new(Runtime::metadata().into())
366		}
367
368		fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
369			Runtime::metadata_at_version(version)
370		}
371
372		fn metadata_versions() -> alloc::vec::Vec<u32> {
373			Runtime::metadata_versions()
374		}
375	}
376
377	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
378		fn slot_duration() -> sp_consensus_aura::SlotDuration {
379			sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
380		}
381
382		fn authorities() -> Vec<AuraId> {
383			pallet_aura::Authorities::<Runtime>::get().into_inner()
384		}
385	}
386
387	impl cumulus_primitives_core::RelayParentOffsetApi<Block> for Runtime {
388		fn relay_parent_offset() -> u32 {
389			RELAY_PARENT_OFFSET
390		}
391	}
392
393	impl cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> for Runtime {
394		fn can_build_upon(
395			included_hash: <Block as BlockT>::Hash,
396			slot: cumulus_primitives_aura::Slot,
397		) -> bool {
398			ConsensusHook::can_build_upon(included_hash, slot)
399		}
400	}
401
402	impl sp_block_builder::BlockBuilder<Block> for Runtime {
403		fn apply_extrinsic(
404			extrinsic: <Block as BlockT>::Extrinsic,
405		) -> ApplyExtrinsicResult {
406			Executive::apply_extrinsic(extrinsic)
407		}
408
409		fn finalize_block() -> <Block as BlockT>::Header {
410			Executive::finalize_block()
411		}
412
413		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
414			data.create_extrinsics()
415		}
416
417		fn check_inherents(block: <Block as BlockT>::LazyBlock, data: sp_inherents::InherentData) -> sp_inherents::CheckInherentsResult {
418			data.check_extrinsics(&block)
419		}
420	}
421
422	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
423		fn validate_transaction(
424			source: TransactionSource,
425			tx: <Block as BlockT>::Extrinsic,
426			block_hash: <Block as BlockT>::Hash,
427		) -> TransactionValidity {
428			Executive::validate_transaction(source, tx, block_hash)
429		}
430	}
431
432	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
433		fn offchain_worker(header: &<Block as BlockT>::Header) {
434			Executive::offchain_worker(header)
435		}
436	}
437
438	impl sp_session::SessionKeys<Block> for Runtime {
439		fn generate_session_keys(owner: Vec<u8>, seed: Option<Vec<u8>>) -> OpaqueGeneratedSessionKeys {
440			SessionKeys::generate(&owner, seed).into()
441		}
442
443		fn decode_session_keys(
444			encoded: Vec<u8>,
445		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
446			SessionKeys::decode_into_raw_public_keys(&encoded)
447		}
448	}
449
450	impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
451		fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
452			ParachainSystem::collect_collation_info(header)
453		}
454	}
455
456	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
457		fn account_nonce(account: AccountId) -> Nonce {
458			System::account_nonce(account)
459		}
460	}
461
462	#[cfg(feature = "runtime-benchmarks")]
463	impl frame_benchmarking::Benchmark<Block> for Runtime {
464		fn benchmark_metadata(extra: bool) -> (
465			Vec<frame_benchmarking::BenchmarkList>,
466			Vec<frame_support::traits::StorageInfo>,
467		) {
468			use frame_benchmarking::BenchmarkList;
469			use frame_support::traits::StorageInfoTrait;
470			use frame_system_benchmarking::Pallet as SystemBench;
471			use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench;
472
473			let mut list = Vec::<BenchmarkList>::new();
474			list_benchmarks!(list, extra);
475
476			let storage_info = AllPalletsWithSystem::storage_info();
477
478			(list, storage_info)
479		}
480
481		#[allow(non_local_definitions)]
482		fn dispatch_benchmark(
483			config: frame_benchmarking::BenchmarkConfig
484		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
485			use frame_benchmarking::{BenchmarkBatch,  BenchmarkError};
486			use sp_storage::TrackedStorageKey;
487
488			use frame_system_benchmarking::Pallet as SystemBench;
489			use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench;
490			impl frame_system_benchmarking::Config for Runtime {
491				fn setup_set_code_requirements(code: &alloc::vec::Vec<u8>) -> Result<(), BenchmarkError> {
492					ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
493					Ok(())
494				}
495
496				fn verify_set_code() {
497					System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
498				}
499			}
500
501			use frame_support::traits::WhitelistedStorageKeys;
502			let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
503
504			let mut batches = Vec::<BenchmarkBatch>::new();
505			let params = (&config, &whitelist);
506			add_benchmarks!(params, batches);
507			Ok(batches)
508		}
509	}
510
511	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
512		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
513			build_state::<RuntimeGenesisConfig>(config)
514		}
515
516		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
517			get_preset::<RuntimeGenesisConfig>(id, &genesis_config_presets::get_preset)
518		}
519
520		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
521			genesis_config_presets::preset_names()
522		}
523	}
524
525	impl cumulus_primitives_core::GetParachainInfo<Block> for Runtime {
526		fn parachain_id() -> ParaId {
527			ParachainInfo::parachain_id()
528		}
529	}
530
531	impl cumulus_primitives_core::TargetBlockRate<Block> for Runtime {
532		fn target_block_rate() -> u32 {
533			BLOCK_PROCESSING_VELOCITY
534		}
535	}
536}
537
538cumulus_pallet_parachain_system::register_validate_block! {
539	Runtime = Runtime,
540	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
541}