1#![cfg_attr(not(feature = "std"), no_std)]
19
20pub mod endpoint;
21pub mod messages;
22
23#[cfg(not(feature = "std"))]
24extern crate alloc;
25
26use crate::messages::{MessageKey, Nonce};
27#[cfg(not(feature = "std"))]
28use alloc::collections::BTreeSet;
29#[cfg(not(feature = "std"))]
30use alloc::vec::Vec;
31#[cfg(feature = "std")]
32use frame_support::inherent::InherentData;
33use frame_support::inherent::{InherentIdentifier, IsFatalError};
34use messages::{BlockMessagesWithStorageKey, ChannelId, CrossDomainMessage, MessageId};
35use parity_scale_codec::{Decode, Encode};
36use scale_info::TypeInfo;
37use sp_domains::{ChainId, DomainAllowlistUpdates, DomainId};
38use sp_subspace_mmr::ConsensusChainMmrLeafProof;
39#[cfg(feature = "std")]
40use std::collections::BTreeSet;
41
42pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"messengr";
44
45pub const MAX_FUTURE_ALLOWED_NONCES: u32 = 256;
54
55pub trait OnXDMRewards<Balance> {
57 fn on_xdm_rewards(rewards: Balance);
58 fn on_chain_protocol_fees(chain_id: ChainId, fees: Balance);
59}
60
61impl<Balance> OnXDMRewards<Balance> for () {
62 fn on_xdm_rewards(_: Balance) {}
63
64 fn on_chain_protocol_fees(_chain_id: ChainId, _fees: Balance) {}
65}
66
67pub trait DomainRegistration {
69 fn is_domain_registered(domain_id: DomainId) -> bool;
70}
71
72impl DomainRegistration for () {
73 fn is_domain_registered(_domain_id: DomainId) -> bool {
74 false
75 }
76}
77
78pub trait StorageKeys {
80 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option<Vec<u8>>;
82
83 fn outbox_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>>;
85
86 fn inbox_responses_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>>;
88}
89
90impl StorageKeys for () {
91 fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Option<Vec<u8>> {
92 None
93 }
94
95 fn outbox_storage_key(_chain_id: ChainId, _message_key: MessageKey) -> Option<Vec<u8>> {
96 None
97 }
98
99 fn inbox_responses_storage_key(
100 _chain_id: ChainId,
101 _message_key: MessageKey,
102 ) -> Option<Vec<u8>> {
103 None
104 }
105}
106
107#[derive(Debug, Encode, Decode)]
109pub struct InherentType {
110 pub maybe_updates: Option<DomainAllowlistUpdates>,
111}
112
113#[derive(Debug, Encode)]
115#[cfg_attr(feature = "std", derive(Decode))]
116pub enum InherentError {
117 MissingAllowlistUpdates,
118 IncorrectAllowlistUpdates,
119}
120
121impl IsFatalError for InherentError {
122 fn is_fatal_error(&self) -> bool {
123 true
124 }
125}
126
127#[cfg(feature = "std")]
129pub struct InherentDataProvider {
130 data: InherentType,
131}
132
133#[cfg(feature = "std")]
134impl InherentDataProvider {
135 pub fn new(data: InherentType) -> Self {
137 Self { data }
138 }
139
140 pub fn data(&self) -> &InherentType {
142 &self.data
143 }
144}
145
146#[cfg(feature = "std")]
147#[async_trait::async_trait]
148impl sp_inherents::InherentDataProvider for InherentDataProvider {
149 async fn provide_inherent_data(
150 &self,
151 inherent_data: &mut InherentData,
152 ) -> Result<(), sp_inherents::Error> {
153 inherent_data.put_data(INHERENT_IDENTIFIER, &self.data)
154 }
155
156 async fn try_handle_error(
157 &self,
158 identifier: &InherentIdentifier,
159 error: &[u8],
160 ) -> Option<Result<(), sp_inherents::Error>> {
161 if *identifier != INHERENT_IDENTIFIER {
162 return None;
163 }
164
165 let error = InherentError::decode(&mut &*error).ok()?;
166
167 Some(Err(sp_inherents::Error::Application(Box::from(format!(
168 "{error:?}"
169 )))))
170 }
171}
172
173#[derive(Debug, Encode, Decode, TypeInfo, Copy, Clone)]
175pub enum XdmId {
176 RelayMessage(MessageKey),
177 RelayResponseMessage(MessageKey),
178}
179
180impl XdmId {
181 pub fn get_chain_id_and_channel_id(&self) -> (ChainId, ChannelId) {
182 match self {
183 XdmId::RelayMessage(key) => (key.0, key.1),
184 XdmId::RelayResponseMessage(key) => (key.0, key.1),
185 }
186 }
187}
188
189#[derive(Debug, Encode, Decode, TypeInfo, Copy, Clone)]
190pub struct ChannelNonce {
191 pub relay_msg_nonce: Option<Nonce>,
194 pub relay_response_msg_nonce: Option<Nonce>,
197}
198
199sp_api::decl_runtime_apis! {
200 #[api_version(2)]
202 pub trait RelayerApi<BlockNumber, CNumber, CHash>
203 where
204 BlockNumber: Encode + Decode,
205 CNumber: Encode + Decode,
206 CHash: Encode + Decode,
207 {
208 fn block_messages() -> BlockMessagesWithStorageKey;
211
212 fn outbox_message_unsigned(
214 msg: CrossDomainMessage<CNumber, CHash, sp_core::H256>,
215 ) -> Option<Block::Extrinsic>;
216
217 fn inbox_response_message_unsigned(
219 msg: CrossDomainMessage<CNumber, CHash, sp_core::H256>,
220 ) -> Option<Block::Extrinsic>;
221
222 fn should_relay_outbox_message(dst_chain_id: ChainId, msg_id: MessageId) -> bool;
224
225 fn should_relay_inbox_message_response(dst_chain_id: ChainId, msg_id: MessageId) -> bool;
227
228 fn updated_channels() -> BTreeSet<(ChainId, ChannelId)>;
230
231 fn channel_storage_key(chain_id: ChainId, channel_id: ChannelId) -> Vec<u8>;
233
234 fn open_channels() -> BTreeSet<(ChainId, ChannelId)>;
236 }
237
238 #[api_version(2)]
240 pub trait MessengerApi<CNumber, CHash>
241 where
242 CNumber: Encode + Decode,
243 CHash: Encode + Decode,
244 {
245 fn is_xdm_mmr_proof_valid(
248 ext: &Block::Extrinsic
249 ) -> Option<bool>;
250
251 fn extract_xdm_mmr_proof(ext: &Block::Extrinsic) -> Option<ConsensusChainMmrLeafProof<CNumber, CHash, sp_core::H256>>;
253
254 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec<u8>;
256
257 fn outbox_storage_key(message_key: MessageKey) -> Vec<u8>;
259
260 fn inbox_response_storage_key(message_key: MessageKey) -> Vec<u8>;
262
263 fn domain_chains_allowlist_update(domain_id: DomainId) -> Option<DomainAllowlistUpdates>;
265
266 fn xdm_id(ext: &Block::Extrinsic) -> Option<XdmId>;
268
269 fn channel_nonce(chain_id: ChainId, channel_id: ChannelId) -> Option<ChannelNonce>;
271 }
272}