1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Cumulus.
3

            
4
// Substrate 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
// Substrate 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

            
30
extern crate alloc;
31

            
32
use cumulus_primitives_core::{
33
	relay_chain::{BlakeTwo256, Hash as RelayHash, HashT as _},
34
	InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData,
35
};
36

            
37
use alloc::{collections::btree_map::BTreeMap, vec::Vec};
38
use scale_info::TypeInfo;
39
use sp_inherents::InherentIdentifier;
40

            
41
/// The identifier for the parachain inherent.
42
pub 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)]
46
pub 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]
68
impl 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)]
98
pub struct MessageQueueChain(RelayHash);
99

            
100
impl 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
}