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