cumulus_primitives_parachain_inherent/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3
4// Cumulus is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Cumulus is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Cumulus parachain inherent
18//!
19//! The [`ParachainInherentData`] is the data that is passed by the collator to the parachain
20//! runtime. The runtime will use this data to execute messages from other parachains/the relay
21//! chain or to read data from the relay chain state. When the parachain is validated by a parachain
22//! validator on the relay chain, this data is checked for correctness. If the data passed by the
23//! collator to the runtime isn't correct, the parachain candidate is considered invalid.
24//!
25//! To create a [`ParachainInherentData`] for a specific relay chain block, there exists the
26//! `ParachainInherentDataExt` trait in `cumulus-client-parachain-inherent` that helps with this.
27
28#![cfg_attr(not(feature = "std"), no_std)]
29
30extern crate alloc;
31
32use cumulus_primitives_core::{
33	relay_chain::{BlakeTwo256, Hash as RelayHash, HashT as _},
34	InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData,
35};
36
37use alloc::{collections::btree_map::BTreeMap, vec::Vec};
38use scale_info::TypeInfo;
39use sp_inherents::InherentIdentifier;
40
41/// The identifier for the parachain inherent.
42pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"sysi1337";
43
44/// The inherent data that is passed by the collator to the parachain runtime.
45#[derive(codec::Encode, codec::Decode, sp_core::RuntimeDebug, Clone, PartialEq, TypeInfo)]
46pub struct ParachainInherentData {
47	pub validation_data: PersistedValidationData,
48	/// A storage proof of a predefined set of keys from the relay-chain.
49	///
50	/// Specifically this witness contains the data for:
51	///
52	/// - the current slot number at the given relay parent
53	/// - active host configuration as per the relay parent,
54	/// - the relay dispatch queue sizes
55	/// - the list of egress HRMP channels (in the list of recipients form)
56	/// - the metadata for the egress HRMP channels
57	pub relay_chain_state: sp_trie::StorageProof,
58	/// Downward messages in the order they were sent.
59	pub downward_messages: Vec<InboundDownwardMessage>,
60	/// HRMP messages grouped by channels. The messages in the inner vec must be in order they
61	/// were sent. In combination with the rule of no more than one message in a channel per block,
62	/// this means `sent_at` is **strictly** greater than the previous one (if any).
63	pub horizontal_messages: BTreeMap<ParaId, Vec<InboundHrmpMessage>>,
64}
65
66#[cfg(feature = "std")]
67#[async_trait::async_trait]
68impl sp_inherents::InherentDataProvider for ParachainInherentData {
69	async fn provide_inherent_data(
70		&self,
71		inherent_data: &mut sp_inherents::InherentData,
72	) -> Result<(), sp_inherents::Error> {
73		inherent_data.put_data(INHERENT_IDENTIFIER, &self)
74	}
75
76	async fn try_handle_error(
77		&self,
78		_: &sp_inherents::InherentIdentifier,
79		_: &[u8],
80	) -> Option<Result<(), sp_inherents::Error>> {
81		None
82	}
83}
84
85/// This struct provides ability to extend a message queue chain (MQC) and compute a new head.
86///
87/// MQC is an instance of a [hash chain] applied to a message queue. Using a hash chain it's
88/// possible to represent a sequence of messages using only a single hash.
89///
90/// A head for an empty chain is agreed to be a zero hash.
91///
92/// An instance is used to track either DMP from the relay chain or HRMP across a channel.
93/// But a given instance is never used to track both. Therefore, you should call either
94/// `extend_downward` or `extend_hrmp`, but not both methods on a single instance.
95///
96/// [hash chain]: https://en.wikipedia.org/wiki/Hash_chain
97#[derive(Default, Clone, codec::Encode, codec::Decode, scale_info::TypeInfo)]
98pub struct MessageQueueChain(RelayHash);
99
100impl MessageQueueChain {
101	/// Create a new instance initialized to `hash`.
102	pub fn new(hash: RelayHash) -> Self {
103		Self(hash)
104	}
105
106	/// Extend the hash chain with an HRMP message. This method should be used only when
107	/// this chain is tracking HRMP.
108	pub fn extend_hrmp(&mut self, horizontal_message: &InboundHrmpMessage) -> &mut Self {
109		let prev_head = self.0;
110		self.0 = BlakeTwo256::hash_of(&(
111			prev_head,
112			horizontal_message.sent_at,
113			BlakeTwo256::hash_of(&horizontal_message.data),
114		));
115		self
116	}
117
118	/// Extend the hash chain with a downward message. This method should be used only when
119	/// this chain is tracking DMP.
120	pub fn extend_downward(&mut self, downward_message: &InboundDownwardMessage) -> &mut Self {
121		let prev_head = self.0;
122		self.0 = BlakeTwo256::hash_of(&(
123			prev_head,
124			downward_message.sent_at,
125			BlakeTwo256::hash_of(&downward_message.msg),
126		));
127		self
128	}
129
130	/// Return the current mead of the message queue hash chain.
131	/// This is agreed to be the zero hash for an empty chain.
132	pub fn head(&self) -> RelayHash {
133		self.0
134	}
135}