referrerpolicy=no-referrer-when-downgrade

cumulus_pallet_parachain_system/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#![cfg_attr(not(feature = "std"), no_std)]
18
19//! `cumulus-pallet-parachain-system` is a base pallet for Cumulus-based parachains.
20//!
21//! This pallet handles low-level details of being a parachain. Its responsibilities include:
22//!
23//! - ingestion of the parachain validation data;
24//! - ingestion and dispatch of incoming downward and lateral messages;
25//! - coordinating upgrades with the Relay Chain; and
26//! - communication of parachain outputs, such as sent messages, signaling an upgrade, etc.
27//!
28//! Users must ensure that they register this pallet as an inherent provider.
29
30extern crate alloc;
31
32use alloc::{collections::btree_map::BTreeMap, vec, vec::Vec};
33use codec::{Decode, Encode};
34use core::cmp;
35use cumulus_primitives_core::{
36	relay_chain::{self, UMPSignal, UMP_SEPARATOR},
37	AbridgedHostConfiguration, ChannelInfo, ChannelStatus, CollationInfo, CoreInfo,
38	CumulusDigestItem, GetChannelInfo, ListChannelInfos, MessageSendError, OutboundHrmpMessage,
39	ParaId, PersistedValidationData, UpwardMessage, UpwardMessageSender, VerifySchedulingSignature,
40	XcmpMessageHandler, XcmpMessageSource,
41};
42use cumulus_primitives_parachain_inherent::{v0, MessageQueueChain, ParachainInherentData};
43use frame_support::{
44	dispatch::{DispatchClass, DispatchResult},
45	ensure,
46	inherent::{InherentData, InherentIdentifier, ProvideInherent},
47	traits::{Get, HandleMessage},
48	weights::Weight,
49};
50use frame_system::{ensure_none, ensure_root, pallet_prelude::HeaderFor};
51use parachain_inherent::{
52	deconstruct_parachain_inherent_data, AbridgedInboundDownwardMessages,
53	AbridgedInboundHrmpMessages, BasicParachainInherentData, InboundMessageId, InboundMessagesData,
54};
55use polkadot_parachain_primitives::primitives::RelayChainBlockNumber;
56use polkadot_runtime_parachains::{FeeTracker, GetMinFeeFactor};
57use scale_info::TypeInfo;
58use sp_runtime::{
59	traits::{BlockNumberProvider, Hash},
60	Debug, FixedU128, SaturatedConversion,
61};
62use xcm::{latest::XcmHash, VersionedLocation, VersionedXcm};
63use xcm_builder::InspectMessageQueues;
64
65mod benchmarking;
66pub mod block_weight;
67pub mod consensus_hook;
68pub mod migration;
69mod mock;
70pub mod relay_state_snapshot;
71#[cfg(test)]
72mod tests;
73mod unincluded_segment;
74pub mod weights;
75#[macro_use]
76pub mod validate_block;
77mod descendant_validation;
78pub mod parachain_inherent;
79
80use unincluded_segment::{
81	HrmpChannelUpdate, HrmpWatermarkUpdate, OutboundBandwidthLimits, SegmentTracker,
82};
83
84pub use consensus_hook::{ConsensusHook, ExpectParentIncluded};
85/// Register the `validate_block` function that is used by parachains to validate blocks on a
86/// validator.
87///
88/// Does *nothing* when `std` feature is enabled.
89///
90/// Expects as parameters the runtime, a block executor and an inherent checker.
91///
92/// # Example
93///
94/// ```
95///     struct BlockExecutor;
96///     struct Runtime;
97///
98///     cumulus_pallet_parachain_system::register_validate_block! {
99///         Runtime = Runtime,
100///         BlockExecutor = Executive,
101///     }
102///
103/// # fn main() {}
104/// ```
105pub use cumulus_pallet_parachain_system_proc_macro::register_validate_block;
106pub use relay_state_snapshot::{MessagingStateSnapshot, RelayChainStateProof};
107pub use unincluded_segment::{Ancestor, UsedBandwidth};
108pub use weights::WeightInfo;
109
110use crate::parachain_inherent::AbridgedInboundMessagesSizeInfo;
111pub use pallet::*;
112
113const LOG_TARGET: &str = "runtime::parachain-system";
114
115/// Tracks cumulative UMP and HRMP message counts sent across blocks within a single PoV.
116#[derive(Encode, Decode, Clone, Debug, TypeInfo, Default)]
117pub struct PoVMessages {
118	/// Relay parent storage root of the current PoV.
119	pub relay_storage_root_or_hash: relay_chain::Hash,
120	/// The core selector of the current Pov.
121	pub core_selector: u8,
122	/// The bundle index of the current PoV. `None` when `BundleInfo` digest is absent.
123	pub bundle_index: u8,
124	/// Cumulative count of UMP messages sent in this PoV.
125	pub ump_msg_count: u32,
126	/// Cumulative count of HRMP outbound messages sent in this PoV.
127	pub hrmp_outbound_count: u32,
128	/// Recipients already used for HRMP outbound messages in this PoV.
129	pub hrmp_outbound_recipients: Vec<ParaId>,
130}
131
132/// Something that can check the associated relay block number.
133///
134/// Each Parachain block is built in the context of a relay chain block, this trait allows us
135/// to validate the given relay chain block number. With async backing it is legal to build
136/// multiple Parachain blocks per relay chain parent. With this trait it is possible for the
137/// Parachain to ensure that still only one Parachain block is build per relay chain parent.
138///
139/// By default [`RelayNumberStrictlyIncreases`] and [`AnyRelayNumber`] are provided.
140pub trait CheckAssociatedRelayNumber {
141	/// Check the current relay number versus the previous relay number.
142	///
143	/// The implementation should panic when there is something wrong.
144	fn check_associated_relay_number(
145		current: RelayChainBlockNumber,
146		previous: RelayChainBlockNumber,
147	);
148}
149
150/// Provides an implementation of [`CheckAssociatedRelayNumber`].
151///
152/// It will ensure that the associated relay block number strictly increases between Parachain
153/// blocks. This should be used by production Parachains when in doubt.
154pub struct RelayNumberStrictlyIncreases;
155
156impl CheckAssociatedRelayNumber for RelayNumberStrictlyIncreases {
157	fn check_associated_relay_number(
158		current: RelayChainBlockNumber,
159		previous: RelayChainBlockNumber,
160	) {
161		if current <= previous {
162			panic!("Relay chain block number needs to strictly increase between Parachain blocks!")
163		}
164	}
165}
166
167/// Provides an implementation of [`CheckAssociatedRelayNumber`].
168///
169/// This will accept any relay chain block number combination. This is mainly useful for
170/// test parachains.
171pub struct AnyRelayNumber;
172
173impl CheckAssociatedRelayNumber for AnyRelayNumber {
174	fn check_associated_relay_number(_: RelayChainBlockNumber, _: RelayChainBlockNumber) {}
175}
176
177/// Provides an implementation of [`CheckAssociatedRelayNumber`].
178///
179/// It will ensure that the associated relay block number monotonically increases between Parachain
180/// blocks. This should be used when asynchronous backing is enabled.
181pub struct RelayNumberMonotonicallyIncreases;
182
183impl CheckAssociatedRelayNumber for RelayNumberMonotonicallyIncreases {
184	fn check_associated_relay_number(
185		current: RelayChainBlockNumber,
186		previous: RelayChainBlockNumber,
187	) {
188		if current < previous {
189			panic!(
190				"Relay chain block number needs to monotonically increase between Parachain blocks!"
191			)
192		}
193	}
194}
195
196/// The max length of a DMP message.
197pub type MaxDmpMessageLenOf<T> = <<T as Config>::DmpQueue as HandleMessage>::MaxMessageLen;
198
199pub mod ump_constants {
200	/// `host_config.max_upward_queue_size / THRESHOLD_FACTOR` is the threshold after which delivery
201	/// starts getting exponentially more expensive.
202	/// `2` means the price starts to increase when queue is half full.
203	pub const THRESHOLD_FACTOR: u32 = 2;
204}
205
206const V3_CLAIM_QUEUE_LOOKAHEAD: u8 = 2;
207const V2_CLAIM_QUEUE_LOOKAHEAD: u8 = 1;
208
209/// The largest `claim_queue_offset` a candidate may declare.
210///
211/// With V3 the collator reads the claim queue at the scheduling parent, which is the fresh tip, so
212/// the bound is just the V3 lookahead. Without V3 it reads at the relay parent, which sits
213/// `relay_parent_offset` blocks behind the tip, so the bound grows by that much.
214fn max_allowed_claim_queue_offset(v3_enabled: bool, relay_parent_offset: u8) -> u8 {
215	if v3_enabled {
216		V3_CLAIM_QUEUE_LOOKAHEAD
217	} else {
218		V2_CLAIM_QUEUE_LOOKAHEAD.saturating_add(relay_parent_offset)
219	}
220}
221
222#[frame_support::pallet]
223pub mod pallet {
224	use super::*;
225	use codec::Compact;
226	use cumulus_primitives_core::CoreInfoExistsAtMaxOnce;
227	use frame_support::pallet_prelude::{ValueQuery, *};
228	use frame_system::pallet_prelude::*;
229
230	#[pallet::pallet]
231	#[pallet::storage_version(migration::STORAGE_VERSION)]
232	#[pallet::without_storage_info]
233	pub struct Pallet<T>(_);
234
235	#[pallet::config]
236	pub trait Config: frame_system::Config<OnSetCode = ParachainSetCode<Self>> {
237		/// The overarching event type.
238		#[allow(deprecated)]
239		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
240
241		/// Something which can be notified when the validation data is set.
242		type OnSystemEvent: OnSystemEvent;
243
244		/// Returns the parachain ID we are running with.
245		#[pallet::constant]
246		type SelfParaId: Get<ParaId>;
247
248		/// The place where outbound XCMP messages come from. This is queried in `finalize_block`.
249		type OutboundXcmpMessageSource: XcmpMessageSource;
250
251		/// Queues inbound downward messages for delayed processing.
252		///
253		/// All inbound DMP messages from the relay are pushed into this. The handler is expected to
254		/// eventually process all the messages that are pushed to it.
255		type DmpQueue: HandleMessage;
256
257		/// The weight we reserve at the beginning of the block for processing DMP messages.
258		type ReservedDmpWeight: Get<Weight>;
259
260		/// The message handler that will be invoked when messages are received via XCMP.
261		///
262		/// This should normally link to the XCMP Queue pallet.
263		type XcmpMessageHandler: XcmpMessageHandler;
264
265		/// The weight we reserve at the beginning of the block for processing XCMP messages.
266		type ReservedXcmpWeight: Get<Weight>;
267
268		/// Something that can check the associated relay parent block number.
269		type CheckAssociatedRelayNumber: CheckAssociatedRelayNumber;
270
271		/// Weight info for functions and calls.
272		type WeightInfo: WeightInfo;
273
274		/// An entry-point for higher-level logic to manage the backlog of unincluded parachain
275		/// blocks and authorship rights for those blocks.
276		///
277		/// Typically, this should be a hook tailored to the collator-selection/consensus mechanism
278		/// that is used for this chain.
279		///
280		/// However, to maintain the same behavior as prior to asynchronous backing, provide the
281		/// [`consensus_hook::ExpectParentIncluded`] here. This is only necessary in the case
282		/// that collators aren't expected to have node versions that supply the included block
283		/// in the relay-chain state proof.
284		type ConsensusHook: ConsensusHook;
285
286		/// The offset between the tip of the relay chain and the parent relay block used as parent
287		/// when authoring a parachain block.
288		///
289		/// This setting directly impacts the number of descendant headers that are expected in the
290		/// `set_validation_data` inherent.
291		///
292		/// For any setting `N` larger than zero, the inherent expects that the inherent includes
293		/// the relay parent plus `N` descendants. These headers are required to validate that new
294		/// parachain blocks are authored at the correct offset.
295		///
296		/// While this helps to reduce forks on the parachain side, it increases the delay for
297		/// processing XCM messages. So, the value should be chosen wisely.
298		///
299		/// If set to 0, this config has no impact.
300		type RelayParentOffset: Get<u32>;
301
302		/// Verifier for V3 scheduling proofs.
303		///
304		/// Reports whether V3 scheduling validation is enabled and supplies the
305		/// verification logic for the proof itself. Use `()` to keep V3 scheduling
306		/// disabled.
307		///
308		/// When enabled, this changes how building on older relay parents is enforced:
309		/// - The old `relay_parent_descendants` validation in the inherent is disabled
310		/// - V3 scheduling validation is used instead, with the header chain provided via PVF
311		///   parameters
312		///
313		/// # Migration Guide
314		///
315		/// v3 scheduling is work in progress, and for the moment this should be left as
316		/// `()`. If V3 is wrongfully enabled, the parachain will stall.
317		///
318		/// Before enabling this:
319		/// 1. Ensure all collators are updated to a version that supports V3 candidates
320		/// 2. Ensure the relay chain has `CandidateReceiptV3` node feature enabled
321		/// 3. Swap the verifier for one whose `V3_SCHEDULING_ENABLED` const is `true`, via a
322		///    runtime upgrade.
323		///
324		/// Once enabled, collators will:
325		/// - Stop providing `relay_parent_descendants` in the inherent (empty vec)
326		/// - Provide the header chain via V3 extension in PVF parameters
327		///
328		/// The `RelayParentOffset` config continues to define the header chain length.
329		type SchedulingSignatureVerifier: cumulus_primitives_core::VerifySchedulingSignature;
330	}
331
332	#[pallet::hooks]
333	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
334		/// Handles actually sending upward messages by moving them from `PendingUpwardMessages` to
335		/// `UpwardMessages`. Decreases the delivery fee factor if after sending messages, the queue
336		/// total size is less than the threshold (see [`ump_constants::THRESHOLD_FACTOR`]).
337		/// Also does the sending for HRMP messages it takes from `OutboundXcmpMessageSource`.
338		fn on_finalize(_: BlockNumberFor<T>) {
339			<DidSetValidationCode<T>>::kill();
340			<UpgradeRestrictionSignal<T>>::kill();
341			let relay_upgrade_go_ahead = <UpgradeGoAhead<T>>::take();
342
343			let vfp = <ValidationData<T>>::get().expect(
344				r"Missing required set_validation_data inherent. This inherent must be
345				present in every block. This error typically occurs when the set_validation_data
346				execution failed and was rejected by the block builder. Check earlier log entries
347				for the specific cause of the failure.",
348			);
349
350			LastRelayChainBlockNumber::<T>::put(vfp.relay_parent_number);
351
352			let host_config = match HostConfiguration::<T>::get() {
353				Some(ok) => ok,
354				None => {
355					debug_assert!(
356						false,
357						"host configuration is promised to set until `on_finalize`; qed",
358					);
359					return;
360				},
361			};
362
363			// Before updating the relevant messaging state, we need to extract
364			// the total bandwidth limits for the purpose of updating the unincluded
365			// segment.
366			let total_bandwidth_out = match RelevantMessagingState::<T>::get() {
367				Some(s) => OutboundBandwidthLimits::from_relay_chain_state(&s),
368				None => {
369					debug_assert!(
370						false,
371						"relevant messaging state is promised to be set until `on_finalize`; \
372							qed",
373					);
374					return;
375				},
376			};
377
378			// After this point, the `RelevantMessagingState` in storage reflects the
379			// unincluded segment.
380			Self::adjust_egress_bandwidth_limits();
381
382			let current_core_selector =
383				CumulusDigestItem::find_core_info(&frame_system::Pallet::<T>::digest())
384					.map_or(0, |ci| ci.selector.0);
385
386			let current_bundle_index =
387				CumulusDigestItem::find_block_bundle_info(&frame_system::Pallet::<T>::digest())
388					.map_or(0, |bi| bi.index);
389
390			let mut pov_tracker = PoVMessagesTracker::<T>::get()
391				.filter(|tracker| {
392					// If the relay parent changes, this is for sure a different `PoV`.
393					tracker.relay_storage_root_or_hash == vfp.relay_parent_storage_root &&
394					// A different core selector also means we are on a different `PoV`.
395					tracker.core_selector == current_core_selector &&
396					// The bundle index needs to increase, or we are in a different `PoV`.
397					current_bundle_index > tracker.bundle_index
398				})
399				.unwrap_or_default();
400
401			pov_tracker.bundle_index = current_bundle_index;
402			pov_tracker.core_selector = current_core_selector;
403			pov_tracker.relay_storage_root_or_hash = vfp.relay_parent_storage_root;
404
405			let (ump_msg_count, ump_total_bytes) = <PendingUpwardMessages<T>>::mutate(|up| {
406				let (available_capacity, available_size) = match RelevantMessagingState::<T>::get()
407				{
408					Some(limits) => (
409						limits.relay_dispatch_queue_remaining_capacity.remaining_count,
410						limits.relay_dispatch_queue_remaining_capacity.remaining_size,
411					),
412					None => {
413						debug_assert!(
414							false,
415							"relevant messaging state is promised to be set until `on_finalize`; \
416								qed",
417						);
418						return (0, 0);
419					},
420				};
421
422				let available_capacity = cmp::min(
423					available_capacity,
424					host_config
425						.max_upward_message_num_per_candidate
426						.saturating_sub(pov_tracker.ump_msg_count),
427				);
428
429				// Count the number of messages we can possibly fit in the given constraints, i.e.
430				// available_capacity and available_size.
431				let (num, total_size) = up
432					.iter()
433					.scan((0u32, 0u32), |state, msg| {
434						let (cap_used, size_used) = *state;
435						let new_cap = cap_used.saturating_add(1);
436						let new_size = size_used.saturating_add(msg.len() as u32);
437						match available_capacity
438							.checked_sub(new_cap)
439							.and(available_size.checked_sub(new_size))
440						{
441							Some(_) => {
442								*state = (new_cap, new_size);
443								Some(*state)
444							},
445							_ => None,
446						}
447					})
448					.last()
449					.unwrap_or_default();
450
451				// TODO: #274 Return back messages that do not longer fit into the queue.
452
453				UpwardMessages::<T>::put(&up[..num as usize]);
454				*up = up.split_off(num as usize);
455
456				pov_tracker.ump_msg_count = pov_tracker.ump_msg_count.saturating_add(num);
457
458				let digest = frame_system::Pallet::<T>::digest();
459
460				let core_info = CumulusDigestItem::find_core_info(&digest);
461				PreviousCoreCount::<T>::put(
462					core_info.as_ref().map_or(Compact(1u16), |ci| ci.number_of_cores),
463				);
464
465				// Only send UMP signals on the last block of a PoV.
466				// For single-block PoVs (no BlockBundleInfo), always send signals.
467				if CumulusDigestItem::is_last_block_in_core(&digest).unwrap_or(true) {
468					Self::send_ump_signals(core_info);
469				}
470
471				// If the total size of the pending messages is less than the threshold,
472				// we decrease the fee factor, since the queue is less congested.
473				// This makes delivery of new messages cheaper.
474				let threshold = host_config
475					.max_upward_queue_size
476					.saturating_div(ump_constants::THRESHOLD_FACTOR);
477				let remaining_total_size: usize = up.iter().map(UpwardMessage::len).sum();
478				if remaining_total_size <= threshold as usize {
479					Self::decrease_fee_factor(());
480				}
481
482				(num, total_size)
483			});
484
485			// Sending HRMP messages is a little bit more involved. There are the following
486			// constraints:
487			//
488			// - a channel should exist (and it can be closed while a message is buffered),
489			// - at most one message can be sent in a channel,
490			// - the sent out messages should be ordered by ascension of recipient para id.
491			// - the capacity and total size of the channel is limited,
492			// - the maximum size of a message is limited (and can potentially be changed),
493
494			let maximum_channels = host_config
495				.hrmp_max_message_num_per_candidate
496				.min(<AnnouncedHrmpMessagesPerCandidate<T>>::take())
497				as usize;
498
499			let maximum_channels =
500				maximum_channels.saturating_sub(pov_tracker.hrmp_outbound_count as usize);
501
502			// Note: this internally calls the `GetChannelInfo` implementation for this
503			// pallet, which draws on the `RelevantMessagingState`. That in turn has
504			// been adjusted above to reflect the correct limits in all channels.
505			let outbound_messages = T::OutboundXcmpMessageSource::take_outbound_messages(
506				maximum_channels,
507				&pov_tracker.hrmp_outbound_recipients,
508			)
509			.into_iter()
510			.map(|(recipient, data)| OutboundHrmpMessage { recipient, data })
511			.collect::<Vec<_>>();
512
513			pov_tracker
514				.hrmp_outbound_recipients
515				.extend(outbound_messages.iter().map(|m| m.recipient));
516			pov_tracker.hrmp_outbound_count =
517				pov_tracker.hrmp_outbound_count.saturating_add(outbound_messages.len() as u32);
518			PoVMessagesTracker::<T>::put(pov_tracker);
519
520			// Update the unincluded segment length; capacity checks were done previously in
521			// `set_validation_data`, so this can be done unconditionally.
522			{
523				let hrmp_outgoing = outbound_messages
524					.iter()
525					.map(|msg| {
526						(
527							msg.recipient,
528							HrmpChannelUpdate { msg_count: 1, total_bytes: msg.data.len() as u32 },
529						)
530					})
531					.collect();
532				let used_bandwidth =
533					UsedBandwidth { ump_msg_count, ump_total_bytes, hrmp_outgoing };
534
535				let mut aggregated_segment =
536					AggregatedUnincludedSegment::<T>::get().unwrap_or_default();
537				let consumed_go_ahead_signal =
538					if aggregated_segment.consumed_go_ahead_signal().is_some() {
539						// Some ancestor within the segment already processed this signal --
540						// validated during inherent creation.
541						None
542					} else {
543						relay_upgrade_go_ahead
544					};
545				// The bandwidth constructed was ensured to satisfy relay chain constraints.
546				let ancestor = Ancestor::new_unchecked(used_bandwidth, consumed_go_ahead_signal);
547
548				let watermark = HrmpWatermark::<T>::get();
549				let watermark_update = HrmpWatermarkUpdate::new(watermark, vfp.relay_parent_number);
550
551				aggregated_segment
552					.append(&ancestor, watermark_update, &total_bandwidth_out)
553					.expect("unincluded segment limits exceeded");
554				AggregatedUnincludedSegment::<T>::put(aggregated_segment);
555				// Check in `on_initialize` guarantees there's space for this block.
556				UnincludedSegment::<T>::append(ancestor);
557			}
558
559			HrmpOutboundMessages::<T>::put(outbound_messages);
560		}
561
562		fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
563			let mut weight = Weight::zero();
564
565			// To prevent removing `NewValidationCode` that was set by another `on_initialize`
566			// like for example from scheduler, we only kill the storage entry if it was not yet
567			// updated in the current block.
568			if !<DidSetValidationCode<T>>::get() {
569				// NOTE: Killing here is required to at least include the trie nodes down to the key
570				// in the proof. Because this value will be read in `validate_block` and thus,
571				// needs to be reachable by the proof.
572				NewValidationCode::<T>::kill();
573				weight += T::DbWeight::get().writes(1);
574			}
575
576			// The parent hash was unknown during block finalization. Update it here.
577			{
578				<UnincludedSegment<T>>::mutate(|chain| {
579					if let Some(ancestor) = chain.last_mut() {
580						let parent = frame_system::Pallet::<T>::parent_hash();
581						// Ancestor is the latest finalized block, thus current parent is
582						// its output head.
583						ancestor.replace_para_head_hash(parent);
584					}
585				});
586				weight += T::DbWeight::get().reads_writes(1, 1);
587
588				// Weight used during finalization.
589				weight += T::DbWeight::get().reads_writes(3, 2);
590			}
591
592			BlockWeightMode::<T>::kill();
593
594			// Remove the validation from the old block.
595			ValidationData::<T>::kill();
596			// NOTE: Killing here is required to at least include the trie nodes down to the keys
597			// in the proof. Because these values will be read in `validate_block` and thus,
598			// need to be reachable by the proof.
599			ProcessedDownwardMessages::<T>::kill();
600			UpwardMessages::<T>::kill();
601			HrmpOutboundMessages::<T>::kill();
602			CustomValidationHeadData::<T>::kill();
603			// The same as above. Reading here to make sure that the key is included in the proof.
604			HrmpWatermark::<T>::get();
605			weight += T::DbWeight::get().reads_writes(1, 5);
606
607			// Here, in `on_initialize` we must report the weight for both `on_initialize` and
608			// `on_finalize`.
609			//
610			// One complication here, is that the `host_configuration` is updated by an inherent
611			// and those are processed after the block initialization phase. Therefore, we have to
612			// be content only with the configuration as per the previous block. That means that
613			// the configuration can be either stale (or be absent altogether in case of the
614			// beginning of the chain).
615			//
616			// In order to mitigate this, we do the following. At the time, we are only concerned
617			// about `hrmp_max_message_num_per_candidate`. We reserve the amount of weight to
618			// process the number of HRMP messages according to the potentially stale
619			// configuration. In `on_finalize` we will process only the maximum between the
620			// announced number of messages and the actual received in the fresh configuration.
621			//
622			// In the common case, they will be the same. In the case the actual value is smaller
623			// than the announced, we would waste some of weight. In the case the actual value is
624			// greater than the announced, we will miss opportunity to send a couple of messages.
625			weight += T::DbWeight::get().reads_writes(1, 1);
626			let hrmp_max_message_num_per_candidate = HostConfiguration::<T>::get()
627				.map(|cfg| cfg.hrmp_max_message_num_per_candidate)
628				.unwrap_or(0);
629			<AnnouncedHrmpMessagesPerCandidate<T>>::put(hrmp_max_message_num_per_candidate);
630
631			// NOTE that the actual weight consumed by `on_finalize` may turn out lower.
632			weight += T::DbWeight::get().reads_writes(
633				3 + hrmp_max_message_num_per_candidate as u64,
634				4 + hrmp_max_message_num_per_candidate as u64,
635			);
636
637			// Weight for updating the last relay chain block number in `on_finalize`.
638			weight += T::DbWeight::get().reads_writes(1, 1);
639
640			// Weight for adjusting the unincluded segment in `on_finalize`.
641			weight += T::DbWeight::get().reads_writes(6, 3);
642
643			// Always try to read `UpgradeGoAhead` in `on_finalize`.
644			weight += T::DbWeight::get().reads(1);
645
646			// Ensure `CoreInfo` digest exists only once and validate claim_queue_offset.
647			match CumulusDigestItem::core_info_exists_at_max_once(
648				&frame_system::Pallet::<T>::digest(),
649			) {
650				CoreInfoExistsAtMaxOnce::Once(core_info) => {
651					let max_allowed_offset = max_allowed_claim_queue_offset(
652						T::SchedulingSignatureVerifier::V3_SCHEDULING_ENABLED,
653						T::RelayParentOffset::get().saturated_into::<u8>(),
654					);
655					assert!(
656						core_info.claim_queue_offset.0 <= max_allowed_offset,
657						"claim_queue_offset {} exceeds maximum allowed {}",
658						core_info.claim_queue_offset.0,
659						max_allowed_offset,
660					);
661				},
662				CoreInfoExistsAtMaxOnce::NotFound => {},
663				CoreInfoExistsAtMaxOnce::MoreThanOnce => {
664					panic!("`CumulusDigestItem::CoreInfo` must exist at max once.");
665				},
666			}
667
668			weight
669		}
670	}
671
672	#[pallet::call]
673	impl<T: Config> Pallet<T> {
674		/// Set the current validation data.
675		///
676		/// This should be invoked exactly once per block. It will panic at the finalization
677		/// phase if the call was not invoked.
678		///
679		/// The dispatch origin for this call must be `Inherent`
680		///
681		/// As a side effect, this function upgrades the current validation function
682		/// if the appropriate time has come.
683		#[pallet::call_index(0)]
684		#[pallet::weight((0, DispatchClass::Mandatory))]
685		// TODO: This weight should be corrected. Currently the weight is registered manually in the
686		// call with `register_extra_weight_unchecked`.
687		pub fn set_validation_data(
688			origin: OriginFor<T>,
689			data: BasicParachainInherentData,
690			inbound_messages_data: InboundMessagesData,
691		) -> DispatchResult {
692			ensure_none(origin)?;
693			assert!(
694				!<ValidationData<T>>::exists(),
695				"ValidationData must be updated only once in a block",
696			);
697
698			// TODO: This is more than zero, but will need benchmarking to figure out what.
699			let mut total_weight = Weight::zero();
700
701			// NOTE: the inherent data is expected to be unique, even if this block is build
702			// in the context of the same relay parent as the previous one. In particular,
703			// the inherent shouldn't contain messages that were already processed by any of the
704			// ancestors.
705			//
706			// This invariant should be upheld by the `ProvideInherent` implementation.
707			let BasicParachainInherentData {
708				validation_data: vfp,
709				relay_chain_state,
710				relay_parent_descendants,
711				collator_peer_id,
712			} = data;
713
714			// Check that the associated relay chain block number is as expected.
715			T::CheckAssociatedRelayNumber::check_associated_relay_number(
716				vfp.relay_parent_number,
717				LastRelayChainBlockNumber::<T>::get(),
718			);
719
720			let relay_state_proof = RelayChainStateProof::new(
721				T::SelfParaId::get(),
722				vfp.relay_parent_storage_root,
723				relay_chain_state.clone(),
724			)
725			.expect("Invalid relay chain state proof");
726
727			// Relay parent offset validation:
728			// When V3 scheduling is disabled: validate relay_parent_descendants (old mechanism)
729			// When V3 scheduling is enabled: skip this validation, V3 scheduling validation
730			// happens in validate_block with header chain from PVF params
731			let expected_rp_descendants_num = T::RelayParentOffset::get();
732			let v3_enabled = T::SchedulingSignatureVerifier::V3_SCHEDULING_ENABLED;
733
734			if expected_rp_descendants_num > 0 && !v3_enabled {
735				if let Err(err) = descendant_validation::verify_relay_parent_descendants(
736					&relay_state_proof,
737					relay_parent_descendants,
738					vfp.relay_parent_storage_root,
739					expected_rp_descendants_num,
740				) {
741					panic!(
742						"Unable to verify provided relay parent descendants. \
743						expected_rp_descendants_num: {expected_rp_descendants_num} \
744						error: {err:?}"
745					);
746				};
747			}
748
749			// Update the desired maximum capacity according to the consensus hook.
750			let (consensus_hook_weight, capacity) =
751				T::ConsensusHook::on_state_proof(&relay_state_proof);
752			total_weight += consensus_hook_weight;
753			total_weight += Self::maybe_drop_included_ancestors(&relay_state_proof, capacity);
754			// Deposit a log indicating the relay-parent storage root.
755			// TODO: remove this in favor of the relay-parent's hash after
756			// https://github.com/paritytech/cumulus/issues/303
757			frame_system::Pallet::<T>::deposit_log(
758				cumulus_primitives_core::rpsr_digest::relay_parent_storage_root_item(
759					vfp.relay_parent_storage_root,
760					vfp.relay_parent_number,
761				),
762			);
763
764			// Initialization logic: we know that this runs exactly once every block,
765			// which means we can put the initialization logic here to remove the
766			// sequencing problem.
767			let upgrade_go_ahead_signal = relay_state_proof
768				.read_upgrade_go_ahead_signal()
769				.expect("Invalid upgrade go ahead signal");
770
771			let upgrade_signal_in_segment = AggregatedUnincludedSegment::<T>::get()
772				.as_ref()
773				.and_then(SegmentTracker::consumed_go_ahead_signal);
774			if let Some(signal_in_segment) = upgrade_signal_in_segment.as_ref() {
775				// Unincluded ancestor consuming upgrade signal is still within the segment,
776				// sanity check that it matches with the signal from relay chain.
777				assert_eq!(upgrade_go_ahead_signal, Some(*signal_in_segment));
778			}
779			match upgrade_go_ahead_signal {
780				Some(_signal) if upgrade_signal_in_segment.is_some() => {
781					// Do nothing, processing logic was executed by unincluded ancestor.
782				},
783				Some(relay_chain::UpgradeGoAhead::GoAhead) => {
784					assert!(
785						<PendingValidationCode<T>>::exists(),
786						"No new validation function found in storage, GoAhead signal is not expected",
787					);
788					let validation_code = <PendingValidationCode<T>>::take();
789
790					frame_system::Pallet::<T>::update_code_in_storage(&validation_code);
791					<T::OnSystemEvent as OnSystemEvent>::on_validation_code_applied();
792					Self::deposit_event(Event::ValidationFunctionApplied {
793						relay_chain_block_num: vfp.relay_parent_number,
794					});
795				},
796				Some(relay_chain::UpgradeGoAhead::Abort) => {
797					<PendingValidationCode<T>>::kill();
798					Self::deposit_event(Event::ValidationFunctionDiscarded);
799				},
800				None => {},
801			}
802			<UpgradeRestrictionSignal<T>>::put(
803				relay_state_proof
804					.read_upgrade_restriction_signal()
805					.expect("Invalid upgrade restriction signal"),
806			);
807			<UpgradeGoAhead<T>>::put(upgrade_go_ahead_signal);
808
809			let host_config = relay_state_proof
810				.read_abridged_host_configuration()
811				.expect("Invalid host configuration in relay chain state proof");
812
813			let relevant_messaging_state = relay_state_proof
814				.read_messaging_state_snapshot(&host_config)
815				.expect("Invalid messaging state in relay chain state proof");
816
817			<ValidationData<T>>::put(&vfp);
818			<RelayStateProof<T>>::put(relay_chain_state);
819			<RelevantMessagingState<T>>::put(relevant_messaging_state.clone());
820			<HostConfiguration<T>>::put(host_config);
821
822			total_weight.saturating_accrue(
823				<T::OnSystemEvent as OnSystemEvent>::on_relay_state_proof(&relay_state_proof),
824			);
825
826			<T::OnSystemEvent as OnSystemEvent>::on_validation_data(&vfp);
827
828			match collator_peer_id {
829				Some(peer_id) => PendingApprovedPeer::<T>::put(peer_id),
830				None => PendingApprovedPeer::<T>::kill(),
831			}
832
833			total_weight.saturating_accrue(Self::enqueue_inbound_downward_messages(
834				relevant_messaging_state.dmq_mqc_head,
835				inbound_messages_data.downward_messages,
836			));
837			total_weight.saturating_accrue(Self::enqueue_inbound_horizontal_messages(
838				&relevant_messaging_state.ingress_channels,
839				inbound_messages_data.horizontal_messages,
840				vfp.relay_parent_number,
841			));
842
843			frame_system::Pallet::<T>::register_extra_weight_unchecked(
844				total_weight,
845				DispatchClass::Mandatory,
846			);
847
848			Ok(())
849		}
850
851		#[pallet::call_index(1)]
852		#[pallet::weight((1_000, DispatchClass::Operational))]
853		pub fn sudo_send_upward_message(
854			origin: OriginFor<T>,
855			message: UpwardMessage,
856		) -> DispatchResult {
857			ensure_root(origin)?;
858			let _ = Self::send_upward_message(message);
859			Ok(())
860		}
861
862		// WARNING: call indices 2 and 3 were used in a former version of this pallet. Using them
863		// again will require to bump the transaction version of runtimes using this pallet.
864	}
865
866	#[pallet::event]
867	#[pallet::generate_deposit(pub(super) fn deposit_event)]
868	pub enum Event<T: Config> {
869		/// The validation function has been scheduled to apply.
870		ValidationFunctionStored,
871		/// The validation function was applied as of the contained relay chain block number.
872		ValidationFunctionApplied { relay_chain_block_num: RelayChainBlockNumber },
873		/// The relay-chain aborted the upgrade process.
874		ValidationFunctionDiscarded,
875		/// Some downward messages have been received and will be processed.
876		DownwardMessagesReceived { count: u32 },
877		/// Downward messages were processed using the given weight.
878		DownwardMessagesProcessed { weight_used: Weight, dmq_head: relay_chain::Hash },
879		/// An upward message was sent to the relay chain.
880		UpwardMessageSent { message_hash: Option<XcmHash> },
881	}
882
883	#[pallet::error]
884	pub enum Error<T> {
885		/// Attempt to upgrade validation function while existing upgrade pending.
886		OverlappingUpgrades,
887		/// Polkadot currently prohibits this parachain from upgrading its validation function.
888		ProhibitedByPolkadot,
889		/// The supplied validation function has compiled into a blob larger than Polkadot is
890		/// willing to run.
891		TooBig,
892		/// The inherent which supplies the validation data did not run this block.
893		ValidationDataNotAvailable,
894		/// The inherent which supplies the host configuration did not run this block.
895		HostConfigurationNotAvailable,
896		/// No validation function upgrade is currently scheduled.
897		NotScheduled,
898	}
899
900	/// The current block weight mode.
901	///
902	/// This is used to determine what is the maximum allowed block weight, for more information see
903	/// [`block_weight`].
904	///
905	/// Killed in [`Self::on_initialize`] and set by the [`block_weight`] logic.
906	#[pallet::storage]
907	#[pallet::whitelist_storage]
908	pub type BlockWeightMode<T: Config> =
909		StorageValue<_, block_weight::BlockWeightMode<T>, OptionQuery>;
910
911	/// The core count available to the parachain in the previous block.
912	///
913	/// This is mainly used for offchain functionality to calculate the correct target block weight.
914	#[pallet::storage]
915	#[pallet::whitelist_storage]
916	pub type PreviousCoreCount<T: Config> = StorageValue<_, Compact<u16>, OptionQuery>;
917
918	/// Latest included block descendants the runtime accepted. In other words, these are
919	/// ancestors of the currently executing block which have not been included in the observed
920	/// relay-chain state.
921	///
922	/// The segment length is limited by the capacity returned from the [`ConsensusHook`] configured
923	/// in the pallet.
924	#[pallet::storage]
925	pub type UnincludedSegment<T: Config> = StorageValue<_, Vec<Ancestor<T::Hash>>, ValueQuery>;
926
927	/// Storage field that keeps track of bandwidth used by the unincluded segment along with the
928	/// latest HRMP watermark. Used for limiting the acceptance of new blocks with
929	/// respect to relay chain constraints.
930	#[pallet::storage]
931	pub type AggregatedUnincludedSegment<T: Config> =
932		StorageValue<_, SegmentTracker<T::Hash>, OptionQuery>;
933
934	/// In case of a scheduled upgrade, this storage field contains the validation code to be
935	/// applied.
936	///
937	/// As soon as the relay chain gives us the go-ahead signal, we will overwrite the
938	/// [`:pending_code`][sp_core::storage::well_known_keys::PENDING_CODE] which will result the
939	/// next block to be processed with the new validation code. This concludes the upgrade process.
940	#[pallet::storage]
941	pub type PendingValidationCode<T: Config> = StorageValue<_, Vec<u8>, ValueQuery>;
942
943	/// Validation code that is set by the parachain and is to be communicated to collator and
944	/// consequently the relay-chain.
945	///
946	/// This will be cleared in `on_initialize` of each new block if no other pallet already set
947	/// the value.
948	#[pallet::storage]
949	pub type NewValidationCode<T: Config> = StorageValue<_, Vec<u8>, OptionQuery>;
950
951	/// The [`PersistedValidationData`] set for this block.
952	///
953	/// This value is expected to be set only once by the [`Pallet::set_validation_data`] inherent.
954	#[pallet::storage]
955	pub type ValidationData<T: Config> = StorageValue<_, PersistedValidationData>;
956
957	/// Were the validation data set to notify the relay chain?
958	#[pallet::storage]
959	pub type DidSetValidationCode<T: Config> = StorageValue<_, bool, ValueQuery>;
960
961	/// The relay chain block number associated with the last parachain block.
962	///
963	/// This is updated in `on_finalize`.
964	#[pallet::storage]
965	pub type LastRelayChainBlockNumber<T: Config> =
966		StorageValue<_, RelayChainBlockNumber, ValueQuery>;
967
968	/// An option which indicates if the relay-chain restricts signalling a validation code upgrade.
969	/// In other words, if this is `Some` and [`NewValidationCode`] is `Some` then the produced
970	/// candidate will be invalid.
971	///
972	/// This storage item is a mirror of the corresponding value for the current parachain from the
973	/// relay-chain. This value is ephemeral which means it doesn't hit the storage. This value is
974	/// set after the inherent.
975	#[pallet::storage]
976	pub type UpgradeRestrictionSignal<T: Config> =
977		StorageValue<_, Option<relay_chain::UpgradeRestriction>, ValueQuery>;
978
979	/// Optional upgrade go-ahead signal from the relay-chain.
980	///
981	/// This storage item is a mirror of the corresponding value for the current parachain from the
982	/// relay-chain. This value is ephemeral which means it doesn't hit the storage. This value is
983	/// set after the inherent.
984	#[pallet::storage]
985	pub type UpgradeGoAhead<T: Config> =
986		StorageValue<_, Option<relay_chain::UpgradeGoAhead>, ValueQuery>;
987
988	/// The state proof for the last relay parent block.
989	///
990	/// This field is meant to be updated each block with the validation data inherent. Therefore,
991	/// before processing of the inherent, e.g. in `on_initialize` this data may be stale.
992	///
993	/// This data is also absent from the genesis.
994	#[pallet::storage]
995	pub type RelayStateProof<T: Config> = StorageValue<_, sp_trie::StorageProof>;
996
997	/// The snapshot of some state related to messaging relevant to the current parachain as per
998	/// the relay parent.
999	///
1000	/// This field is meant to be updated each block with the validation data inherent. Therefore,
1001	/// before processing of the inherent, e.g. in `on_initialize` this data may be stale.
1002	///
1003	/// This data is also absent from the genesis.
1004	#[pallet::storage]
1005	pub type RelevantMessagingState<T: Config> = StorageValue<_, MessagingStateSnapshot>;
1006
1007	/// The parachain host configuration that was obtained from the relay parent.
1008	///
1009	/// This field is meant to be updated each block with the validation data inherent. Therefore,
1010	/// before processing of the inherent, e.g. in `on_initialize` this data may be stale.
1011	///
1012	/// This data is also absent from the genesis.
1013	#[pallet::storage]
1014	#[pallet::disable_try_decode_storage]
1015	pub type HostConfiguration<T: Config> = StorageValue<_, AbridgedHostConfiguration>;
1016
1017	/// The last downward message queue chain head we have observed.
1018	///
1019	/// This value is loaded before and saved after processing inbound downward messages carried
1020	/// by the system inherent.
1021	#[pallet::storage]
1022	pub type LastDmqMqcHead<T: Config> = StorageValue<_, MessageQueueChain, ValueQuery>;
1023
1024	/// The message queue chain heads we have observed per each channel incoming channel.
1025	///
1026	/// This value is loaded before and saved after processing inbound downward messages carried
1027	/// by the system inherent.
1028	#[pallet::storage]
1029	pub type LastHrmpMqcHeads<T: Config> =
1030		StorageValue<_, BTreeMap<ParaId, MessageQueueChain>, ValueQuery>;
1031
1032	/// Number of downward messages processed in a block.
1033	///
1034	/// This will be cleared in `on_initialize` of each new block.
1035	#[pallet::storage]
1036	pub type ProcessedDownwardMessages<T: Config> = StorageValue<_, u32, ValueQuery>;
1037
1038	/// The last processed downward message.
1039	///
1040	/// We need to keep track of this to filter the messages that have been already processed.
1041	#[pallet::storage]
1042	pub type LastProcessedDownwardMessage<T: Config> = StorageValue<_, InboundMessageId>;
1043
1044	/// HRMP watermark that was set in a block.
1045	#[pallet::storage]
1046	pub type HrmpWatermark<T: Config> = StorageValue<_, relay_chain::BlockNumber, ValueQuery>;
1047
1048	/// The last processed HRMP message.
1049	///
1050	/// We need to keep track of this to filter the messages that have been already processed.
1051	#[pallet::storage]
1052	pub type LastProcessedHrmpMessage<T: Config> = StorageValue<_, InboundMessageId>;
1053
1054	/// HRMP messages that were sent in a block.
1055	///
1056	/// This will be cleared in `on_initialize` of each new block.
1057	#[pallet::storage]
1058	pub type HrmpOutboundMessages<T: Config> =
1059		StorageValue<_, Vec<OutboundHrmpMessage>, ValueQuery>;
1060
1061	/// Upward messages that were sent in a block.
1062	///
1063	/// This will be cleared in `on_initialize` for each new block.
1064	#[pallet::storage]
1065	pub type UpwardMessages<T: Config> = StorageValue<_, Vec<UpwardMessage>, ValueQuery>;
1066
1067	/// Upward messages that are still pending and not yet sent to the relay chain.
1068	#[pallet::storage]
1069	pub type PendingUpwardMessages<T: Config> = StorageValue<_, Vec<UpwardMessage>, ValueQuery>;
1070
1071	/// Upward signals that are still pending and not yet sent to the relay chain.
1072	///
1073	/// This will be cleared in `on_finalize` for each block.
1074	#[pallet::storage]
1075	pub type PendingUpwardSignals<T: Config> = StorageValue<_, Vec<UpwardMessage>, ValueQuery>;
1076
1077	/// The approved peer id to be sent as a UMP signal on the last block of the PoV.
1078	#[pallet::storage]
1079	pub type PendingApprovedPeer<T: Config> =
1080		StorageValue<_, relay_chain::ApprovedPeerId, OptionQuery>;
1081
1082	/// The factor to multiply the base delivery fee by for UMP.
1083	#[pallet::storage]
1084	pub type UpwardDeliveryFeeFactor<T: Config> =
1085		StorageValue<_, FixedU128, ValueQuery, GetMinFeeFactor<Pallet<T>>>;
1086
1087	/// The number of HRMP messages we observed in `on_initialize` and thus used that number for
1088	/// announcing the weight of `on_initialize` and `on_finalize`.
1089	#[pallet::storage]
1090	pub type AnnouncedHrmpMessagesPerCandidate<T: Config> = StorageValue<_, u32, ValueQuery>;
1091
1092	/// The weight we reserve at the beginning of the block for processing XCMP messages. This
1093	/// overrides the amount set in the Config trait.
1094	#[pallet::storage]
1095	pub type ReservedXcmpWeightOverride<T: Config> = StorageValue<_, Weight>;
1096
1097	/// The weight we reserve at the beginning of the block for processing DMP messages. This
1098	/// overrides the amount set in the Config trait.
1099	#[pallet::storage]
1100	pub type ReservedDmpWeightOverride<T: Config> = StorageValue<_, Weight>;
1101
1102	/// A custom head data that should be returned as result of `validate_block`.
1103	///
1104	/// See `Pallet::set_custom_validation_head_data` for more information.
1105	#[pallet::storage]
1106	pub type CustomValidationHeadData<T: Config> = StorageValue<_, Vec<u8>, OptionQuery>;
1107
1108	/// Tracks cumulative `UMP` and `HRMP` messages sent across blocks in the current `PoV`.
1109	///
1110	/// Across different candidates/PoVs the budgets are tracked by [`AggregatedUnincludedSegment`].
1111	#[pallet::storage]
1112	pub type PoVMessagesTracker<T: Config> = StorageValue<_, PoVMessages, OptionQuery>;
1113
1114	#[pallet::inherent]
1115	impl<T: Config> ProvideInherent for Pallet<T> {
1116		type Call = Call<T>;
1117		type Error = sp_inherents::MakeFatalError<()>;
1118		const INHERENT_IDENTIFIER: InherentIdentifier =
1119			cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER;
1120
1121		fn create_inherent(data: &InherentData) -> Option<Self::Call> {
1122			let data = match data
1123				.get_data::<ParachainInherentData>(&Self::INHERENT_IDENTIFIER)
1124				.ok()
1125				.flatten()
1126			{
1127				None => {
1128					// Key Self::INHERENT_IDENTIFIER is expected to contain versioned inherent
1129					// data. Older nodes are unaware of the new format and might provide the
1130					// legacy data format. We try to load it and transform it into the current
1131					// version.
1132					let data = data
1133						.get_data::<v0::ParachainInherentData>(
1134							&cumulus_primitives_parachain_inherent::PARACHAIN_INHERENT_IDENTIFIER_V0,
1135						)
1136						.ok()
1137						.flatten()?;
1138					data.into()
1139				},
1140				Some(data) => data,
1141			};
1142
1143			Some(Self::do_create_inherent(data))
1144		}
1145
1146		fn is_inherent(call: &Self::Call) -> bool {
1147			matches!(call, Call::set_validation_data { .. })
1148		}
1149	}
1150
1151	#[pallet::genesis_config]
1152	#[derive(frame_support::DefaultNoBound)]
1153	pub struct GenesisConfig<T: Config> {
1154		#[serde(skip)]
1155		pub _config: core::marker::PhantomData<T>,
1156	}
1157
1158	#[pallet::genesis_build]
1159	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
1160		fn build(&self) {
1161			// TODO: Remove after https://github.com/paritytech/cumulus/issues/479
1162			sp_io::storage::set(b":c", &[]);
1163		}
1164	}
1165}
1166
1167impl<T: Config> Pallet<T> {
1168	/// Get the unincluded segment size after the given hash.
1169	///
1170	/// If the unincluded segment doesn't contain the given hash, this returns the
1171	/// length of the entire unincluded segment.
1172	///
1173	/// This is intended to be used for determining how long the unincluded segment _would be_
1174	/// in runtime APIs related to authoring.
1175	pub fn unincluded_segment_size_after(included_hash: T::Hash) -> u32 {
1176		let segment = UnincludedSegment::<T>::get();
1177		crate::unincluded_segment::size_after_included(included_hash, &segment)
1178	}
1179
1180	/// Returns the configured maximum claim queue offset.
1181	///
1182	/// This is used by the [cumulus_primitives_core::RelayParentOffsetApi::max_claim_queue_offset]
1183	/// runtime API to expose the value to collators.
1184	pub fn max_claim_queue_offset() -> u8 {
1185		if !T::SchedulingSignatureVerifier::V3_SCHEDULING_ENABLED {
1186			return V2_CLAIM_QUEUE_LOOKAHEAD;
1187		}
1188
1189		V3_CLAIM_QUEUE_LOOKAHEAD
1190	}
1191}
1192
1193impl<T: Config> FeeTracker for Pallet<T> {
1194	type Id = ();
1195
1196	fn get_fee_factor(_id: Self::Id) -> FixedU128 {
1197		UpwardDeliveryFeeFactor::<T>::get()
1198	}
1199
1200	fn set_fee_factor(_id: Self::Id, val: FixedU128) {
1201		UpwardDeliveryFeeFactor::<T>::set(val);
1202	}
1203}
1204
1205impl<T: Config> ListChannelInfos for Pallet<T> {
1206	fn outgoing_channels() -> Vec<ParaId> {
1207		let Some(state) = RelevantMessagingState::<T>::get() else { return Vec::new() };
1208		state.egress_channels.into_iter().map(|(id, _)| id).collect()
1209	}
1210}
1211
1212impl<T: Config> GetChannelInfo for Pallet<T> {
1213	fn get_channel_status(id: ParaId) -> ChannelStatus {
1214		// Note, that we are using `relevant_messaging_state` which may be from the previous
1215		// block, in case this is called from `on_initialize`, i.e. before the inherent with
1216		// fresh data is submitted.
1217		//
1218		// That shouldn't be a problem though because this is anticipated and already can
1219		// happen. This is because sending implies that a message is buffered until there is
1220		// space to send a message in the candidate. After a while waiting in a buffer, it may
1221		// be discovered that the channel to which a message were addressed is now closed.
1222		// Another possibility, is that the maximum message size was decreased so that a
1223		// message in the buffer doesn't fit. Should any of that happen the sender should be
1224		// notified about the message was discarded.
1225		//
1226		// Here it a similar case, with the difference that the realization that the channel is
1227		// closed came the same block.
1228		let channels = match RelevantMessagingState::<T>::get() {
1229			None => {
1230				log::warn!("calling `get_channel_status` with no RelevantMessagingState?!");
1231				return ChannelStatus::Closed;
1232			},
1233			Some(d) => d.egress_channels,
1234		};
1235		// ^^^ NOTE: This storage field should carry over from the previous block. So if it's
1236		// None then it must be that this is an edge-case where a message is attempted to be
1237		// sent at the first block. It should be safe to assume that there are no channels
1238		// opened at all so early. At least, relying on this assumption seems to be a better
1239		// trade-off, compared to introducing an error variant that the clients should be
1240		// prepared to handle.
1241		let index = match channels.binary_search_by_key(&id, |item| item.0) {
1242			Err(_) => return ChannelStatus::Closed,
1243			Ok(i) => i,
1244		};
1245		let meta = &channels[index].1;
1246		if meta.msg_count + 1 > meta.max_capacity {
1247			// The channel is at its capacity. Skip it for now.
1248			return ChannelStatus::Full;
1249		}
1250		let max_size_now = meta.max_total_size - meta.total_size;
1251		let max_size_ever = meta.max_message_size;
1252		ChannelStatus::Ready(max_size_now as usize, max_size_ever as usize)
1253	}
1254
1255	fn get_channel_info(id: ParaId) -> Option<ChannelInfo> {
1256		let channels = RelevantMessagingState::<T>::get()?.egress_channels;
1257		let index = channels.binary_search_by_key(&id, |item| item.0).ok()?;
1258		let info = ChannelInfo {
1259			max_capacity: channels[index].1.max_capacity,
1260			max_total_size: channels[index].1.max_total_size,
1261			max_message_size: channels[index].1.max_message_size,
1262			msg_count: channels[index].1.msg_count,
1263			total_size: channels[index].1.total_size,
1264		};
1265		Some(info)
1266	}
1267}
1268
1269impl<T: Config> Pallet<T> {
1270	/// The bandwidth limit per block that applies when receiving messages from the relay chain via
1271	/// DMP or XCMP.
1272	///
1273	/// The limit is per message passing mechanism (e.g. 1 MiB for DMP, 1 MiB for XCMP).
1274	///
1275	/// The purpose of this limit is to make sure that the total size of the messages received by
1276	/// the parachain from the relay chain doesn't exceed the block size. Currently each message
1277	/// passing mechanism can use 1/6 of the total block PoV which means that in total 1/3
1278	/// of the block PoV can be used for message passing.
1279	fn messages_collection_size_limit() -> usize {
1280		let max_block_weight = <T as frame_system::Config>::BlockWeights::get().max_block;
1281		let max_block_pov = max_block_weight.proof_size();
1282
1283		let remaining_proof_size =
1284			frame_system::Pallet::<T>::remaining_block_weight().remaining().proof_size();
1285
1286		(max_block_pov / 6).min(remaining_proof_size).saturated_into()
1287	}
1288
1289	/// Updates inherent data to only include the messages that weren't already processed
1290	/// by the runtime and to compress (hash) the messages that exceed the allocated size.
1291	///
1292	/// This method doesn't check for mqc heads mismatch. If the MQC doesn't match after
1293	/// dropping messages, the runtime will panic when executing the inherent.
1294	fn do_create_inherent(data: ParachainInherentData) -> Call<T> {
1295		let (data, mut downward_messages, mut horizontal_messages) =
1296			deconstruct_parachain_inherent_data(data);
1297		let last_relay_block_number = LastRelayChainBlockNumber::<T>::get();
1298
1299		let messages_collection_size_limit = Self::messages_collection_size_limit();
1300		// DMQ.
1301		let last_processed_msg = LastProcessedDownwardMessage::<T>::get()
1302			.unwrap_or(InboundMessageId { sent_at: last_relay_block_number, reverse_idx: 0 });
1303		downward_messages.drop_processed_messages(&last_processed_msg);
1304		let mut size_limit = messages_collection_size_limit;
1305		let downward_messages = downward_messages.into_abridged(&mut size_limit);
1306
1307		// HRMP.
1308		let last_processed_msg = LastProcessedHrmpMessage::<T>::get()
1309			.unwrap_or(InboundMessageId { sent_at: last_relay_block_number, reverse_idx: 0 });
1310		horizontal_messages.drop_processed_messages(&last_processed_msg);
1311		size_limit = size_limit.saturating_add(messages_collection_size_limit);
1312		let horizontal_messages = horizontal_messages.into_abridged(&mut size_limit);
1313
1314		let inbound_messages_data =
1315			InboundMessagesData::new(downward_messages, horizontal_messages);
1316
1317		Call::set_validation_data { data, inbound_messages_data }
1318	}
1319
1320	/// Enqueue all inbound downward messages relayed by the collator into the MQ pallet.
1321	///
1322	/// Checks if the sequence of the messages is valid, dispatches them and communicates the
1323	/// number of processed messages to the collator via a storage update.
1324	///
1325	/// # Panics
1326	///
1327	/// If it turns out that after processing all messages the Message Queue Chain
1328	/// hash doesn't match the expected.
1329	fn enqueue_inbound_downward_messages(
1330		expected_dmq_mqc_head: relay_chain::Hash,
1331		downward_messages: AbridgedInboundDownwardMessages,
1332	) -> Weight {
1333		downward_messages.check_enough_messages_included_basic("DMQ");
1334
1335		let mut dmq_head = <LastDmqMqcHead<T>>::get();
1336
1337		let (messages, hashed_messages) = downward_messages.messages();
1338		let message_count = messages.len() as u32;
1339		let weight_used = T::WeightInfo::enqueue_inbound_downward_messages(message_count);
1340		if let Some(last_msg) = messages.last() {
1341			Self::deposit_event(Event::DownwardMessagesReceived { count: message_count });
1342
1343			// Eagerly update the MQC head hash:
1344			for msg in messages {
1345				dmq_head.extend_downward(msg);
1346			}
1347			<LastDmqMqcHead<T>>::put(&dmq_head);
1348			Self::deposit_event(Event::DownwardMessagesProcessed {
1349				weight_used,
1350				dmq_head: dmq_head.head(),
1351			});
1352
1353			let mut last_processed_msg =
1354				InboundMessageId { sent_at: last_msg.sent_at, reverse_idx: 0 };
1355			for msg in hashed_messages {
1356				dmq_head.extend_with_hashed_msg(msg);
1357
1358				if msg.sent_at == last_processed_msg.sent_at {
1359					last_processed_msg.reverse_idx += 1;
1360				}
1361			}
1362			LastProcessedDownwardMessage::<T>::put(last_processed_msg);
1363
1364			T::DmpQueue::handle_messages(downward_messages.bounded_msgs_iter());
1365		}
1366
1367		// After hashing each message in the message queue chain submitted by the collator, we
1368		// should arrive to the MQC head provided by the relay chain.
1369		//
1370		// A mismatch means that at least some of the submitted messages were altered, omitted or
1371		// added improperly.
1372		assert_eq!(dmq_head.head(), expected_dmq_mqc_head, "DMQ head mismatch");
1373
1374		ProcessedDownwardMessages::<T>::put(message_count);
1375
1376		weight_used
1377	}
1378
1379	fn get_ingress_channel_or_panic(
1380		ingress_channels: &[(ParaId, cumulus_primitives_core::AbridgedHrmpChannel)],
1381		sender: ParaId,
1382	) -> &cumulus_primitives_core::AbridgedHrmpChannel {
1383		let maybe_channel_idx = ingress_channels
1384			.binary_search_by_key(&sender, |&(channel_sender, _)| channel_sender)
1385			.ok();
1386		let maybe_channel = maybe_channel_idx
1387			.and_then(|channel_idx| ingress_channels.get(channel_idx))
1388			.map(|(_, channel)| channel);
1389		maybe_channel.unwrap_or_else(|| {
1390			panic!(
1391				"One of the messages submitted by the collator was sent from a sender ({}) \
1392				that doesn't have a channel opened to this parachain",
1393				<ParaId as Into<u32>>::into(sender)
1394			)
1395		})
1396	}
1397
1398	fn check_hrmp_mcq_heads(
1399		ingress_channels: &[(ParaId, cumulus_primitives_core::AbridgedHrmpChannel)],
1400		mqc_heads: &mut BTreeMap<ParaId, MessageQueueChain>,
1401	) {
1402		// Check that the MQC heads for each channel provided by the relay chain match the MQC
1403		// heads we have after processing all incoming messages.
1404		//
1405		// Along the way we also carry over the relevant entries from the `last_mqc_heads` to
1406		// `running_mqc_heads`. Otherwise, in a block where no messages were sent in a channel
1407		// it won't get into next block's `last_mqc_heads` and thus will be all zeros, which
1408		// would corrupt the message queue chain.
1409		for (sender, channel) in ingress_channels {
1410			let cur_head = mqc_heads.entry(*sender).or_default().head();
1411			let target_head = channel.mqc_head.unwrap_or_default();
1412			assert_eq!(cur_head, target_head, "HRMP head mismatch");
1413		}
1414	}
1415
1416	/// Performs some checks related to the sender and the `sent_at` field of an HRMP message.
1417	///
1418	/// **Panics** if the message submitted by the collator doesn't respect the expected order or if
1419	///            it was sent from a para which has no open channel to this parachain.
1420	fn check_hrmp_message_metadata(
1421		ingress_channels: &[(ParaId, cumulus_primitives_core::AbridgedHrmpChannel)],
1422		maybe_prev_msg_metadata: &mut Option<(u32, ParaId)>,
1423		msg_metadata: (u32, ParaId),
1424	) {
1425		// Check that the message is properly ordered.
1426		if let Some(prev_msg) = maybe_prev_msg_metadata {
1427			assert!(&msg_metadata >= prev_msg, "[HRMP] Messages order violation");
1428		}
1429		*maybe_prev_msg_metadata = Some(msg_metadata);
1430
1431		// Check that the message is sent from an existing channel.
1432		Self::get_ingress_channel_or_panic(ingress_channels, msg_metadata.1);
1433	}
1434
1435	/// Process all inbound horizontal messages relayed by the collator.
1436	///
1437	/// This is similar to [`enqueue_inbound_downward_messages`], but works with multiple inbound
1438	/// channels. It immediately dispatches signals and queues all other XCMs. Blob messages are
1439	/// ignored.
1440	///
1441	/// **Panics** if either any of horizontal messages submitted by the collator was sent from
1442	///            a para which has no open channel to this parachain or if after processing
1443	///            messages across all inbound channels MQCs were obtained which do not
1444	///            correspond to the ones found on the relay-chain.
1445	fn enqueue_inbound_horizontal_messages(
1446		ingress_channels: &[(ParaId, cumulus_primitives_core::AbridgedHrmpChannel)],
1447		horizontal_messages: AbridgedInboundHrmpMessages,
1448		relay_parent_number: relay_chain::BlockNumber,
1449	) -> Weight {
1450		let mut mqc_heads = <LastHrmpMqcHeads<T>>::get();
1451		let (messages, hashed_messages) = horizontal_messages.messages();
1452
1453		// First, check the HRMP advancement rule.
1454		let maybe_first_hashed_msg_sender = hashed_messages.first().map(|(sender, _msg)| *sender);
1455		if let Some(first_hashed_msg_sender) = maybe_first_hashed_msg_sender {
1456			let channel =
1457				Self::get_ingress_channel_or_panic(ingress_channels, first_hashed_msg_sender);
1458			horizontal_messages.check_enough_messages_included_advanced(
1459				"HRMP",
1460				AbridgedInboundMessagesSizeInfo {
1461					max_full_messages_size: Self::messages_collection_size_limit(),
1462					first_hashed_msg_max_size: channel.max_message_size as usize,
1463				},
1464			);
1465		}
1466
1467		Self::prune_closed_mqc_heads(ingress_channels, &mut mqc_heads);
1468
1469		if messages.is_empty() {
1470			Self::check_hrmp_mcq_heads(ingress_channels, &mut mqc_heads);
1471			let last_processed_msg =
1472				InboundMessageId { sent_at: relay_parent_number, reverse_idx: 0 };
1473
1474			LastProcessedHrmpMessage::<T>::put(last_processed_msg);
1475			HrmpWatermark::<T>::put(relay_parent_number);
1476			LastHrmpMqcHeads::<T>::put(&mqc_heads); // write back in case of modification
1477
1478			return T::DbWeight::get().reads_writes(1, 2);
1479		}
1480
1481		let mut prev_msg_metadata = None;
1482		let mut last_processed_block = HrmpWatermark::<T>::get();
1483		let mut last_processed_msg = InboundMessageId { sent_at: 0, reverse_idx: 0 };
1484		for (sender, msg) in messages {
1485			Self::check_hrmp_message_metadata(
1486				ingress_channels,
1487				&mut prev_msg_metadata,
1488				(msg.sent_at, *sender),
1489			);
1490			mqc_heads.entry(*sender).or_default().extend_hrmp(msg);
1491
1492			if msg.sent_at > last_processed_msg.sent_at && last_processed_msg.sent_at > 0 {
1493				last_processed_block = last_processed_msg.sent_at;
1494			}
1495			last_processed_msg.sent_at = msg.sent_at;
1496		}
1497
1498		LastHrmpMqcHeads::<T>::put(&mqc_heads);
1499
1500		for (sender, msg) in hashed_messages {
1501			Self::check_hrmp_message_metadata(
1502				ingress_channels,
1503				&mut prev_msg_metadata,
1504				(msg.sent_at, *sender),
1505			);
1506			mqc_heads.entry(*sender).or_default().extend_with_hashed_msg(msg);
1507
1508			if msg.sent_at == last_processed_msg.sent_at {
1509				last_processed_msg.reverse_idx += 1;
1510			}
1511		}
1512		if last_processed_msg.sent_at > 0 && last_processed_msg.reverse_idx == 0 {
1513			last_processed_block = last_processed_msg.sent_at;
1514		}
1515		LastProcessedHrmpMessage::<T>::put(&last_processed_msg);
1516		Self::check_hrmp_mcq_heads(ingress_channels, &mut mqc_heads);
1517
1518		let max_weight =
1519			<ReservedXcmpWeightOverride<T>>::get().unwrap_or_else(T::ReservedXcmpWeight::get);
1520		let weight_used = T::XcmpMessageHandler::handle_xcmp_messages(
1521			horizontal_messages.flat_msgs_iter(),
1522			max_weight,
1523		);
1524
1525		// Update watermark
1526		HrmpWatermark::<T>::put(last_processed_block);
1527
1528		weight_used.saturating_add(T::DbWeight::get().reads_writes(2, 3))
1529	}
1530
1531	/// Remove all MQC heads that do not correspond to an open channel.
1532	fn prune_closed_mqc_heads(
1533		ingress_channels: &[(ParaId, cumulus_primitives_core::AbridgedHrmpChannel)],
1534		mqc_heads: &mut BTreeMap<ParaId, MessageQueueChain>,
1535	) {
1536		// Complexity is O(N * lg N) but could be optimized for O(N)
1537		mqc_heads.retain(|para, _| {
1538			ingress_channels
1539				.binary_search_by_key(para, |&(channel_sender, _)| channel_sender)
1540				.is_ok()
1541		});
1542	}
1543
1544	/// Drop blocks from the unincluded segment with respect to the latest parachain head.
1545	fn maybe_drop_included_ancestors(
1546		relay_state_proof: &RelayChainStateProof,
1547		capacity: consensus_hook::UnincludedSegmentCapacity,
1548	) -> Weight {
1549		let mut weight_used = Weight::zero();
1550		// If the unincluded segment length is nonzero, then the parachain head must be present.
1551		let para_head =
1552			relay_state_proof.read_included_para_head().ok().map(|h| T::Hashing::hash(&h.0));
1553
1554		let unincluded_segment_len = <UnincludedSegment<T>>::decode_len().unwrap_or(0);
1555		weight_used += T::DbWeight::get().reads(1);
1556
1557		// Clean up unincluded segment if nonempty.
1558		let included_head = match (para_head, capacity.is_expecting_included_parent()) {
1559			(Some(h), true) => {
1560				assert_eq!(
1561					h,
1562					frame_system::Pallet::<T>::parent_hash(),
1563					"expected parent to be included"
1564				);
1565
1566				h
1567			},
1568			(Some(h), false) => h,
1569			(None, true) => {
1570				// All this logic is essentially a workaround to support collators which
1571				// might still not provide the included block with the state proof.
1572				frame_system::Pallet::<T>::parent_hash()
1573			},
1574			(None, false) => panic!("included head not present in relay storage proof"),
1575		};
1576
1577		let new_len = {
1578			let para_head_hash = included_head;
1579			let dropped: Vec<Ancestor<T::Hash>> = <UnincludedSegment<T>>::mutate(|chain| {
1580				// Drop everything up to (inclusive) the block with an included para head, if
1581				// present.
1582				let idx = chain
1583					.iter()
1584					.position(|block| {
1585						let head_hash = block
1586							.para_head_hash()
1587							.expect("para head hash is updated during block initialization; qed");
1588						head_hash == &para_head_hash
1589					})
1590					.map_or(0, |idx| idx + 1); // inclusive.
1591
1592				chain.drain(..idx).collect()
1593			});
1594			weight_used += T::DbWeight::get().reads_writes(1, 1);
1595
1596			let new_len = unincluded_segment_len - dropped.len();
1597			if !dropped.is_empty() {
1598				<AggregatedUnincludedSegment<T>>::mutate(|agg| {
1599					let agg = agg.as_mut().expect(
1600						"dropped part of the segment wasn't empty, hence value exists; qed",
1601					);
1602					for block in dropped {
1603						agg.subtract(&block);
1604					}
1605				});
1606				weight_used += T::DbWeight::get().reads_writes(1, 1);
1607			}
1608
1609			new_len as u32
1610		};
1611
1612		// Current block validity check: ensure there is space in the unincluded segment.
1613		//
1614		// If this fails, the parachain needs to wait for ancestors to be included before
1615		// a new block is allowed.
1616		assert!(
1617			new_len < capacity.get(),
1618			"No space left for the block in the unincluded segment: new_len({new_len}) < capacity({})",
1619			capacity.get()
1620		);
1621		weight_used
1622	}
1623
1624	/// This adjusts the `RelevantMessagingState` according to the bandwidth limits in the
1625	/// unincluded segment.
1626	// Reads: 2
1627	// Writes: 1
1628	fn adjust_egress_bandwidth_limits() {
1629		let Some(unincluded_segment) = AggregatedUnincludedSegment::<T>::get() else { return };
1630
1631		<RelevantMessagingState<T>>::mutate(|messaging_state| {
1632			let Some(messaging_state) = messaging_state else { return };
1633
1634			let used_bandwidth = unincluded_segment.used_bandwidth();
1635
1636			let channels = &mut messaging_state.egress_channels;
1637			for (para_id, used) in used_bandwidth.hrmp_outgoing.iter() {
1638				let Ok(i) = channels.binary_search_by_key(para_id, |item| item.0) else {
1639					continue; // indicates channel closed.
1640				};
1641
1642				let c = &mut channels[i].1;
1643
1644				c.total_size = (c.total_size + used.total_bytes).min(c.max_total_size);
1645				c.msg_count = (c.msg_count + used.msg_count).min(c.max_capacity);
1646			}
1647
1648			let upward_capacity = &mut messaging_state.relay_dispatch_queue_remaining_capacity;
1649			upward_capacity.remaining_count =
1650				upward_capacity.remaining_count.saturating_sub(used_bandwidth.ump_msg_count);
1651			upward_capacity.remaining_size =
1652				upward_capacity.remaining_size.saturating_sub(used_bandwidth.ump_total_bytes);
1653		});
1654	}
1655
1656	/// Put a new validation function into a particular location where polkadot
1657	/// monitors for updates. Calling this function notifies polkadot that a new
1658	/// upgrade has been scheduled.
1659	fn notify_polkadot_of_pending_upgrade(code: &[u8]) {
1660		NewValidationCode::<T>::put(code);
1661		<DidSetValidationCode<T>>::put(true);
1662	}
1663
1664	/// The maximum code size permitted, in bytes.
1665	///
1666	/// Returns `None` if the relay chain parachain host configuration hasn't been submitted yet.
1667	pub fn max_code_size() -> Option<u32> {
1668		<HostConfiguration<T>>::get().map(|cfg| cfg.max_code_size)
1669	}
1670
1671	/// The implementation of the runtime upgrade functionality for parachains.
1672	pub fn schedule_code_upgrade(validation_function: Vec<u8>) -> DispatchResult {
1673		// Ensure that `ValidationData` exists. We do not care about the validation data per se,
1674		// but we do care about the [`UpgradeRestrictionSignal`] which arrives with the same
1675		// inherent.
1676		ensure!(<ValidationData<T>>::exists(), Error::<T>::ValidationDataNotAvailable);
1677		ensure!(<UpgradeRestrictionSignal<T>>::get().is_none(), Error::<T>::ProhibitedByPolkadot);
1678
1679		ensure!(!<PendingValidationCode<T>>::exists(), Error::<T>::OverlappingUpgrades);
1680		let cfg = HostConfiguration::<T>::get().ok_or(Error::<T>::HostConfigurationNotAvailable)?;
1681		ensure!(validation_function.len() <= cfg.max_code_size as usize, Error::<T>::TooBig);
1682
1683		// When a code upgrade is scheduled, it has to be applied in two
1684		// places, synchronized: both polkadot and the individual parachain
1685		// have to upgrade on the same relay chain block.
1686		//
1687		// `notify_polkadot_of_pending_upgrade` notifies polkadot; the `PendingValidationCode`
1688		// storage keeps track locally for the parachain upgrade, which will
1689		// be applied later: when the relay-chain communicates go-ahead signal to us.
1690		Self::notify_polkadot_of_pending_upgrade(&validation_function);
1691		<PendingValidationCode<T>>::put(validation_function);
1692		Self::deposit_event(Event::ValidationFunctionStored);
1693
1694		Ok(())
1695	}
1696
1697	/// Returns the [`CollationInfo`] of the current active block.
1698	///
1699	/// The given `header` is the header of the built block we are collecting the collation info
1700	/// for.
1701	///
1702	/// This is expected to be used by the
1703	/// [`CollectCollationInfo`](cumulus_primitives_core::CollectCollationInfo) runtime api.
1704	pub fn collect_collation_info(header: &HeaderFor<T>) -> CollationInfo {
1705		CollationInfo {
1706			hrmp_watermark: HrmpWatermark::<T>::get(),
1707			horizontal_messages: HrmpOutboundMessages::<T>::get(),
1708			upward_messages: UpwardMessages::<T>::get(),
1709			processed_downward_messages: ProcessedDownwardMessages::<T>::get(),
1710			new_validation_code: NewValidationCode::<T>::get().map(Into::into),
1711			// Check if there is a custom header that will also be returned by the validation phase.
1712			// If so, we need to also return it here.
1713			head_data: CustomValidationHeadData::<T>::get()
1714				.map_or_else(|| header.encode(), |v| v)
1715				.into(),
1716		}
1717	}
1718
1719	/// Set a custom head data that should be returned as result of `validate_block`.
1720	///
1721	/// This will overwrite the head data that is returned as result of `validate_block` while
1722	/// validating a `PoV` on the relay chain. Normally the head data that is being returned
1723	/// by `validate_block` is the header of the block that is validated, thus it can be
1724	/// enacted as the new best block. However, for features like forking it can be useful
1725	/// to overwrite the head data with a custom header.
1726	///
1727	/// # Attention
1728	///
1729	/// This should only be used when you are sure what you are doing as this can brick
1730	/// your Parachain.
1731	pub fn set_custom_validation_head_data(head_data: Vec<u8>) {
1732		CustomValidationHeadData::<T>::put(head_data);
1733	}
1734
1735	/// Send the pending ump signals
1736	fn send_ump_signals(core_info: Option<CoreInfo>) {
1737		let mut ump_signals = PendingUpwardSignals::<T>::take();
1738
1739		if let Some(core_info) = core_info {
1740			ump_signals.push(
1741				UMPSignal::SelectCore(core_info.selector, core_info.claim_queue_offset).encode(),
1742			);
1743		}
1744
1745		if let Some(approved_peer) = PendingApprovedPeer::<T>::take() {
1746			ump_signals.push(UMPSignal::ApprovedPeer(approved_peer).encode());
1747		}
1748
1749		if !ump_signals.is_empty() {
1750			UpwardMessages::<T>::append(UMP_SEPARATOR);
1751			ump_signals.into_iter().for_each(|s| UpwardMessages::<T>::append(s));
1752		}
1753	}
1754
1755	/// Open HRMP channel for using it in benchmarks or tests.
1756	///
1757	/// The caller assumes that the pallet will accept regular outbound message to the sibling
1758	/// `target_parachain` after this call. No other assumptions are made.
1759	#[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
1760	pub fn open_outbound_hrmp_channel_for_benchmarks_or_tests(target_parachain: ParaId) {
1761		RelevantMessagingState::<T>::put(MessagingStateSnapshot {
1762			dmq_mqc_head: Default::default(),
1763			relay_dispatch_queue_remaining_capacity: Default::default(),
1764			ingress_channels: Default::default(),
1765			egress_channels: vec![(
1766				target_parachain,
1767				cumulus_primitives_core::AbridgedHrmpChannel {
1768					max_capacity: 10,
1769					max_total_size: 10_000_000_u32,
1770					max_message_size: 10_000_000_u32,
1771					msg_count: 5,
1772					total_size: 5_000_000_u32,
1773					mqc_head: None,
1774				},
1775			)],
1776		})
1777	}
1778
1779	/// Open HRMP channel for using it in benchmarks or tests.
1780	///
1781	/// The caller assumes that the pallet will accept regular outbound message to the sibling
1782	/// `target_parachain` after this call. No other assumptions are made.
1783	#[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
1784	pub fn open_custom_outbound_hrmp_channel_for_benchmarks_or_tests(
1785		target_parachain: ParaId,
1786		channel: cumulus_primitives_core::AbridgedHrmpChannel,
1787	) {
1788		RelevantMessagingState::<T>::put(MessagingStateSnapshot {
1789			dmq_mqc_head: Default::default(),
1790			relay_dispatch_queue_remaining_capacity: Default::default(),
1791			ingress_channels: Default::default(),
1792			egress_channels: vec![(target_parachain, channel)],
1793		})
1794	}
1795
1796	/// Prepare/insert relevant data for `schedule_code_upgrade` for benchmarks.
1797	#[cfg(feature = "runtime-benchmarks")]
1798	pub fn initialize_for_set_code_benchmark(max_code_size: u32) {
1799		// insert dummy ValidationData
1800		let vfp = PersistedValidationData {
1801			parent_head: polkadot_parachain_primitives::primitives::HeadData(Default::default()),
1802			relay_parent_number: 1,
1803			relay_parent_storage_root: Default::default(),
1804			max_pov_size: 1_000,
1805		};
1806		<ValidationData<T>>::put(&vfp);
1807
1808		// insert dummy HostConfiguration with
1809		let host_config = AbridgedHostConfiguration {
1810			max_code_size,
1811			max_head_data_size: 32 * 1024,
1812			max_upward_queue_count: 8,
1813			max_upward_queue_size: 1024 * 1024,
1814			max_upward_message_size: 4 * 1024,
1815			max_upward_message_num_per_candidate: 2,
1816			hrmp_max_message_num_per_candidate: 2,
1817			validation_upgrade_cooldown: 2,
1818			validation_upgrade_delay: 2,
1819			async_backing_params: relay_chain::AsyncBackingParams {
1820				allowed_ancestry_len: 0,
1821				max_candidate_depth: 0,
1822			},
1823		};
1824		<HostConfiguration<T>>::put(host_config);
1825	}
1826}
1827
1828/// Type that implements `SetCode`.
1829pub struct ParachainSetCode<T>(core::marker::PhantomData<T>);
1830impl<T: Config> frame_system::SetCode<T> for ParachainSetCode<T> {
1831	fn set_code(code: Vec<u8>) -> DispatchResult {
1832		Pallet::<T>::schedule_code_upgrade(code)
1833	}
1834}
1835
1836impl<T: Config> Pallet<T> {
1837	/// Puts a message in the `PendingUpwardMessages` storage item.
1838	/// The message will be later sent in `on_finalize`.
1839	/// Checks host configuration to see if message is too big.
1840	/// Increases the delivery fee factor if the queue is sufficiently (see
1841	/// [`ump_constants::THRESHOLD_FACTOR`]) congested.
1842	pub fn send_upward_message(message: UpwardMessage) -> Result<(u32, XcmHash), MessageSendError> {
1843		let message_len = message.len();
1844		// Check if the message fits into the relay-chain constraints.
1845		//
1846		// Note, that we are using `host_configuration` here which may be from the previous
1847		// block, in case this is called from `on_initialize`, i.e. before the inherent with fresh
1848		// data is submitted.
1849		//
1850		// That shouldn't be a problem since this is a preliminary check and the actual check would
1851		// be performed just before submitting the message from the candidate, and it already can
1852		// happen that during the time the message is buffered for sending the relay-chain setting
1853		// may change so that the message is no longer valid.
1854		//
1855		// However, changing this setting is expected to be rare.
1856		if let Some(cfg) = HostConfiguration::<T>::get() {
1857			if message_len > cfg.max_upward_message_size as usize {
1858				return Err(MessageSendError::TooBig);
1859			}
1860			let threshold =
1861				cfg.max_upward_queue_size.saturating_div(ump_constants::THRESHOLD_FACTOR);
1862			// We check the threshold against total size and not number of messages since messages
1863			// could be big or small.
1864			<PendingUpwardMessages<T>>::append(message.clone());
1865			let pending_messages = PendingUpwardMessages::<T>::get();
1866			let total_size: usize = pending_messages.iter().map(UpwardMessage::len).sum();
1867			if total_size > threshold as usize {
1868				// We increase the fee factor by a factor based on the new message's size in KB
1869				Self::increase_fee_factor((), message_len as u128);
1870			}
1871		} else {
1872			// This storage field should carry over from the previous block. So if it's None
1873			// then it must be that this is an edge-case where a message is attempted to be
1874			// sent at the first block.
1875			//
1876			// Let's pass this message through. I think it's not unreasonable to expect that
1877			// the message is not huge and it comes through, but if it doesn't it can be
1878			// returned back to the sender.
1879			//
1880			// Thus fall through here.
1881			<PendingUpwardMessages<T>>::append(message.clone());
1882		};
1883
1884		// The relay ump does not use using_encoded
1885		// We apply the same this to use the same hash
1886		let hash = sp_io::hashing::blake2_256(&message);
1887		Self::deposit_event(Event::UpwardMessageSent { message_hash: Some(hash) });
1888		Ok((0, hash))
1889	}
1890
1891	/// Get the relay chain block number which was used as an anchor for the last block in this
1892	/// chain.
1893	pub fn last_relay_block_number() -> RelayChainBlockNumber {
1894		LastRelayChainBlockNumber::<T>::get()
1895	}
1896}
1897
1898impl<T: Config> UpwardMessageSender for Pallet<T> {
1899	fn send_upward_message(message: UpwardMessage) -> Result<(u32, XcmHash), MessageSendError> {
1900		Self::send_upward_message(message)
1901	}
1902
1903	fn can_send_upward_message(message: &UpwardMessage) -> Result<(), MessageSendError> {
1904		let max_upward_message_size = HostConfiguration::<T>::get()
1905			.map(|cfg| cfg.max_upward_message_size)
1906			.ok_or(MessageSendError::Other)?;
1907		if message.len() > max_upward_message_size as usize {
1908			Err(MessageSendError::TooBig)
1909		} else {
1910			Ok(())
1911		}
1912	}
1913
1914	#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
1915	fn ensure_successful_delivery() {
1916		const MAX_UPWARD_MESSAGE_SIZE: u32 = 65_531 * 3;
1917		const MAX_CODE_SIZE: u32 = 3 * 1024 * 1024;
1918		HostConfiguration::<T>::mutate(|cfg| match cfg {
1919			Some(cfg) => cfg.max_upward_message_size = MAX_UPWARD_MESSAGE_SIZE,
1920			None => {
1921				*cfg = Some(AbridgedHostConfiguration {
1922					max_code_size: MAX_CODE_SIZE,
1923					max_head_data_size: 32 * 1024,
1924					max_upward_queue_count: 8,
1925					max_upward_queue_size: 1024 * 1024,
1926					max_upward_message_size: MAX_UPWARD_MESSAGE_SIZE,
1927					max_upward_message_num_per_candidate: 2,
1928					hrmp_max_message_num_per_candidate: 2,
1929					validation_upgrade_cooldown: 2,
1930					validation_upgrade_delay: 2,
1931					async_backing_params: relay_chain::AsyncBackingParams {
1932						allowed_ancestry_len: 0,
1933						max_candidate_depth: 0,
1934					},
1935				})
1936			},
1937		})
1938	}
1939}
1940
1941impl<T: Config> InspectMessageQueues for Pallet<T> {
1942	fn clear_messages() {
1943		PendingUpwardMessages::<T>::kill();
1944	}
1945
1946	fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)> {
1947		use xcm::prelude::*;
1948
1949		let messages: Vec<VersionedXcm<()>> = PendingUpwardMessages::<T>::get()
1950			.iter()
1951			.map(|encoded_message| {
1952				VersionedXcm::<()>::decode_all_with_mem_and_depth_limit(&mut &encoded_message[..])
1953					.unwrap()
1954			})
1955			.collect();
1956
1957		if messages.is_empty() {
1958			vec![]
1959		} else {
1960			vec![(VersionedLocation::from(Location::parent()), messages)]
1961		}
1962	}
1963}
1964
1965#[cfg(feature = "runtime-benchmarks")]
1966impl<T: Config> polkadot_runtime_parachains::EnsureForParachain for Pallet<T> {
1967	fn ensure(para_id: ParaId) {
1968		if let ChannelStatus::Closed = Self::get_channel_status(para_id) {
1969			Self::open_outbound_hrmp_channel_for_benchmarks_or_tests(para_id)
1970		}
1971	}
1972}
1973
1974/// Something that should be informed about system related events.
1975///
1976/// This includes events like [`on_validation_data`](Self::on_validation_data) that is being
1977/// called when the parachain inherent is executed that contains the validation data.
1978/// Or like [`on_validation_code_applied`](Self::on_validation_code_applied) that is called
1979/// when the new validation is written to the state. This means that
1980/// from the next block the runtime is being using this new code.
1981pub trait OnSystemEvent {
1982	/// Called in each blocks once when the validation data is set by the inherent.
1983	fn on_validation_data(data: &PersistedValidationData);
1984	/// Called when the validation code is being applied, aka from the next block on this is the new
1985	/// runtime.
1986	fn on_validation_code_applied();
1987	/// Called to process keys from the verified relay chain state proof.
1988	fn on_relay_state_proof(
1989		relay_state_proof: &relay_state_snapshot::RelayChainStateProof,
1990	) -> Weight;
1991}
1992
1993#[impl_trait_for_tuples::impl_for_tuples(30)]
1994impl OnSystemEvent for Tuple {
1995	fn on_validation_data(data: &PersistedValidationData) {
1996		for_tuples!( #( Tuple::on_validation_data(data); )* );
1997	}
1998
1999	fn on_validation_code_applied() {
2000		for_tuples!( #( Tuple::on_validation_code_applied(); )* );
2001	}
2002
2003	fn on_relay_state_proof(
2004		relay_state_proof: &relay_state_snapshot::RelayChainStateProof,
2005	) -> Weight {
2006		let mut weight = Weight::zero();
2007		for_tuples!( #( weight = weight.saturating_add(Tuple::on_relay_state_proof(relay_state_proof)); )* );
2008		weight
2009	}
2010}
2011
2012/// Holds the most recent relay-parent state root and block number of the current parachain block.
2013#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Default, Debug)]
2014pub struct RelayChainState {
2015	/// Current relay chain height.
2016	pub number: relay_chain::BlockNumber,
2017	/// State root for current relay chain height.
2018	pub state_root: relay_chain::Hash,
2019}
2020
2021/// This exposes the [`RelayChainState`] to other runtime modules.
2022///
2023/// Enables parachains to read relay chain state via state proofs.
2024pub trait RelaychainStateProvider {
2025	/// May be called by any runtime module to obtain the current state of the relay chain.
2026	///
2027	/// **NOTE**: This is not guaranteed to return monotonically increasing relay parents.
2028	fn current_relay_chain_state() -> RelayChainState;
2029
2030	/// Utility function only to be used in benchmarking scenarios, to be implemented optionally,
2031	/// else a noop.
2032	///
2033	/// It allows for setting a custom RelayChainState.
2034	#[cfg(feature = "runtime-benchmarks")]
2035	fn set_current_relay_chain_state(_state: RelayChainState) {}
2036}
2037
2038/// Implements [`BlockNumberProvider`] that returns relay chain block number fetched from validation
2039/// data.
2040///
2041/// When validation data is not available (e.g. within `on_initialize`), it will fallback to use
2042/// [`Pallet::last_relay_block_number()`].
2043///
2044/// Implements [`BlockNumberProvider`] and [`RelaychainStateProvider`] that returns relevant relay
2045/// data fetched from validation data.
2046///
2047/// NOTE: When validation data is not available (e.g. within `on_initialize`):
2048///
2049/// - [`current_relay_chain_state`](Self::current_relay_chain_state): Will return the default value
2050///   of [`RelayChainState`].
2051/// - [`current_block_number`](Self::current_block_number): Will return
2052///   [`Pallet::last_relay_block_number()`].
2053pub struct RelaychainDataProvider<T>(core::marker::PhantomData<T>);
2054
2055impl<T: Config> BlockNumberProvider for RelaychainDataProvider<T> {
2056	type BlockNumber = relay_chain::BlockNumber;
2057
2058	fn current_block_number() -> relay_chain::BlockNumber {
2059		ValidationData::<T>::get()
2060			.map(|d| d.relay_parent_number)
2061			.unwrap_or_else(|| Pallet::<T>::last_relay_block_number())
2062	}
2063
2064	#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
2065	fn set_block_number(block: Self::BlockNumber) {
2066		let mut validation_data = ValidationData::<T>::get().unwrap_or_else(||
2067			// PersistedValidationData does not impl default in non-std
2068			PersistedValidationData {
2069				parent_head: vec![].into(),
2070				relay_parent_number: Default::default(),
2071				max_pov_size: Default::default(),
2072				relay_parent_storage_root: Default::default(),
2073			});
2074		validation_data.relay_parent_number = block;
2075		ValidationData::<T>::put(validation_data)
2076	}
2077}
2078
2079impl<T: Config> RelaychainStateProvider for RelaychainDataProvider<T> {
2080	fn current_relay_chain_state() -> RelayChainState {
2081		ValidationData::<T>::get()
2082			.map(|d| RelayChainState {
2083				number: d.relay_parent_number,
2084				state_root: d.relay_parent_storage_root,
2085			})
2086			.unwrap_or_default()
2087	}
2088
2089	#[cfg(feature = "runtime-benchmarks")]
2090	fn set_current_relay_chain_state(state: RelayChainState) {
2091		let mut validation_data = ValidationData::<T>::get().unwrap_or_else(||
2092			// PersistedValidationData does not impl default in non-std
2093			PersistedValidationData {
2094				parent_head: vec![].into(),
2095				relay_parent_number: Default::default(),
2096				max_pov_size: Default::default(),
2097				relay_parent_storage_root: Default::default(),
2098			});
2099		validation_data.relay_parent_number = state.number;
2100		validation_data.relay_parent_storage_root = state.state_root;
2101		ValidationData::<T>::put(validation_data)
2102	}
2103}