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