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::{ChannelStateWithNonce, MessageKey, MessagesWithStorageKey, Nonce};
27#[cfg(not(feature = "std"))]
28use alloc::collections::BTreeMap;
29#[cfg(not(feature = "std"))]
30use alloc::collections::BTreeSet;
31#[cfg(not(feature = "std"))]
32use alloc::vec::Vec;
33#[cfg(feature = "std")]
34use frame_support::inherent::InherentData;
35use frame_support::inherent::{InherentIdentifier, IsFatalError};
36#[cfg(feature = "runtime-benchmarks")]
37use frame_support::storage::storage_prefix;
38#[cfg(feature = "runtime-benchmarks")]
39use frame_support::{Identity, StorageHasher};
40use messages::{BlockMessagesQuery, ChannelId, CrossDomainMessage};
41use parity_scale_codec::{Decode, Encode};
42use scale_info::TypeInfo;
43use sp_domains::{ChainId, DomainAllowlistUpdates, DomainId};
44use sp_subspace_mmr::ConsensusChainMmrLeafProof;
45#[cfg(feature = "std")]
46use std::collections::BTreeMap;
47#[cfg(feature = "std")]
48use std::collections::BTreeSet;
49
50pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"messengr";
52
53pub const MAX_FUTURE_ALLOWED_NONCES: u32 = 256;
62
63pub trait OnXDMRewards<Balance> {
65 fn on_xdm_rewards(rewards: Balance);
66 fn on_chain_protocol_fees(chain_id: ChainId, fees: Balance);
67}
68
69pub trait NoteChainTransfer<Balance> {
71 fn note_transfer_in(amount: Balance, from_chain_id: ChainId) -> bool;
72 fn note_transfer_out(amount: Balance, to_chain_id: ChainId) -> bool;
73}
74
75impl<Balance> NoteChainTransfer<Balance> for () {
76 fn note_transfer_in(_amount: Balance, _from_chain_id: ChainId) -> bool {
77 true
78 }
79 fn note_transfer_out(_amount: Balance, _to_chain_id: ChainId) -> bool {
80 true
81 }
82}
83
84impl<Balance> OnXDMRewards<Balance> for () {
85 fn on_xdm_rewards(_: Balance) {}
86
87 fn on_chain_protocol_fees(_chain_id: ChainId, _fees: Balance) {}
88}
89
90pub trait DomainRegistration {
92 fn is_domain_registered(domain_id: DomainId) -> bool;
93}
94
95impl DomainRegistration for () {
96 fn is_domain_registered(_domain_id: DomainId) -> bool {
97 false
98 }
99}
100
101pub trait StorageKeys {
103 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option<Vec<u8>>;
105
106 fn outbox_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>>;
108
109 fn inbox_responses_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>>;
111}
112
113impl StorageKeys for () {
114 fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Option<Vec<u8>> {
115 None
116 }
117
118 fn outbox_storage_key(_chain_id: ChainId, _message_key: MessageKey) -> Option<Vec<u8>> {
119 None
120 }
121
122 fn inbox_responses_storage_key(
123 _chain_id: ChainId,
124 _message_key: MessageKey,
125 ) -> Option<Vec<u8>> {
126 None
127 }
128}
129
130#[cfg(feature = "runtime-benchmarks")]
131pub struct BenchmarkStorageKeys;
132
133#[cfg(feature = "runtime-benchmarks")]
134impl StorageKeys for BenchmarkStorageKeys {
135 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option<Vec<u8>> {
136 let storage_prefix = storage_prefix(
137 "Domains".as_bytes(),
138 "LatestConfirmedDomainExecutionReceipt".as_bytes(),
139 );
140 let key_hashed = domain_id.using_encoded(Identity::hash);
141
142 let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.len());
143
144 final_key.extend_from_slice(&storage_prefix);
145 final_key.extend_from_slice(key_hashed.as_ref());
146
147 Some(final_key)
148 }
149
150 fn outbox_storage_key(_chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>> {
151 let storage_prefix = storage_prefix("Messenger".as_bytes(), "Outbox".as_bytes());
152 let key_hashed = message_key.using_encoded(Identity::hash);
153
154 let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.len());
155
156 final_key.extend_from_slice(&storage_prefix);
157 final_key.extend_from_slice(key_hashed.as_ref());
158
159 Some(final_key)
160 }
161
162 fn inbox_responses_storage_key(_chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>> {
163 let storage_prefix = storage_prefix("Messenger".as_bytes(), "InboxResponses".as_bytes());
164 let key_hashed = message_key.using_encoded(Identity::hash);
165
166 let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.len());
167
168 final_key.extend_from_slice(&storage_prefix);
169 final_key.extend_from_slice(key_hashed.as_ref());
170
171 Some(final_key)
172 }
173}
174
175#[derive(Debug, Encode, Decode)]
177pub struct InherentType {
178 pub maybe_updates: Option<DomainAllowlistUpdates>,
179}
180
181#[derive(Debug, Encode)]
183#[cfg_attr(feature = "std", derive(Decode))]
184pub enum InherentError {
185 MissingAllowlistUpdates,
186 IncorrectAllowlistUpdates,
187}
188
189impl IsFatalError for InherentError {
190 fn is_fatal_error(&self) -> bool {
191 true
192 }
193}
194
195#[cfg(feature = "std")]
197pub struct InherentDataProvider {
198 data: InherentType,
199}
200
201#[cfg(feature = "std")]
202impl InherentDataProvider {
203 pub fn new(data: InherentType) -> Self {
205 Self { data }
206 }
207
208 pub fn data(&self) -> &InherentType {
210 &self.data
211 }
212}
213
214#[cfg(feature = "std")]
215#[async_trait::async_trait]
216impl sp_inherents::InherentDataProvider for InherentDataProvider {
217 async fn provide_inherent_data(
218 &self,
219 inherent_data: &mut InherentData,
220 ) -> Result<(), sp_inherents::Error> {
221 inherent_data.put_data(INHERENT_IDENTIFIER, &self.data)
222 }
223
224 async fn try_handle_error(
225 &self,
226 identifier: &InherentIdentifier,
227 error: &[u8],
228 ) -> Option<Result<(), sp_inherents::Error>> {
229 if *identifier != INHERENT_IDENTIFIER {
230 return None;
231 }
232
233 let error = InherentError::decode(&mut &*error).ok()?;
234
235 Some(Err(sp_inherents::Error::Application(Box::from(format!(
236 "{error:?}"
237 )))))
238 }
239}
240
241#[derive(Debug, Encode, Decode, TypeInfo, Copy, Clone)]
243pub enum XdmId {
244 RelayMessage(MessageKey),
245 RelayResponseMessage(MessageKey),
246}
247
248impl XdmId {
249 pub fn get_chain_id_and_channel_id(&self) -> (ChainId, ChannelId) {
250 match self {
251 XdmId::RelayMessage(key) => (key.0, key.1),
252 XdmId::RelayResponseMessage(key) => (key.0, key.1),
253 }
254 }
255}
256
257#[derive(Debug, Encode, Decode, TypeInfo, Copy, Clone)]
258pub struct ChannelNonce {
259 pub relay_msg_nonce: Option<Nonce>,
262 pub relay_response_msg_nonce: Option<Nonce>,
265}
266
267sp_api::decl_runtime_apis! {
268 #[api_version(3)]
270 pub trait RelayerApi<BlockNumber, CNumber, CHash>
271 where
272 BlockNumber: Encode + Decode,
273 CNumber: Encode + Decode,
274 CHash: Encode + Decode,
275 {
276 fn outbox_message_unsigned(
278 msg: CrossDomainMessage<CNumber, CHash, sp_core::H256>,
279 ) -> Option<Block::Extrinsic>;
280
281 fn inbox_response_message_unsigned(
283 msg: CrossDomainMessage<CNumber, CHash, sp_core::H256>,
284 ) -> Option<Block::Extrinsic>;
285
286 fn updated_channels() -> BTreeSet<(ChainId, ChannelId)>;
288
289 fn channel_storage_key(chain_id: ChainId, channel_id: ChannelId) -> Vec<u8>;
291
292 fn open_channels() -> BTreeSet<(ChainId, ChannelId)>;
294
295 fn block_messages_with_query(query: BlockMessagesQuery) -> MessagesWithStorageKey;
298
299 fn channels_and_state() -> Vec<(ChainId, ChannelId, ChannelStateWithNonce)>;
301
302 fn first_outbox_message_nonce_to_relay(dst_chain_id: ChainId, channel_id: ChannelId, from_nonce: Nonce) -> Option<Nonce>;
304
305 fn first_inbox_message_response_nonce_to_relay(dst_chain_id: ChainId,channel_id: ChannelId, from_nonce: Nonce) -> Option<Nonce>;
307 }
308
309 #[api_version(3)]
311 pub trait MessengerApi<CNumber, CHash>
312 where
313 CNumber: Encode + Decode,
314 CHash: Encode + Decode,
315 {
316 fn is_xdm_mmr_proof_valid(
319 ext: &Block::Extrinsic
320 ) -> Option<bool>;
321
322 fn extract_xdm_mmr_proof(ext: &Block::Extrinsic) -> Option<ConsensusChainMmrLeafProof<CNumber, CHash, sp_core::H256>>;
324
325 #[allow(clippy::ptr_arg)]
329 fn batch_extract_xdm_mmr_proof(ext: &Vec<Block::Extrinsic>) -> BTreeMap<u32, ConsensusChainMmrLeafProof<CNumber, CHash, sp_core::H256>>;
330
331 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec<u8>;
333
334 fn outbox_storage_key(message_key: MessageKey) -> Vec<u8>;
336
337 fn inbox_response_storage_key(message_key: MessageKey) -> Vec<u8>;
339
340 fn domain_chains_allowlist_update(domain_id: DomainId) -> Option<DomainAllowlistUpdates>;
342
343 fn xdm_id(ext: &Block::Extrinsic) -> Option<XdmId>;
345
346 fn channel_nonce(chain_id: ChainId, channel_id: ChannelId) -> Option<ChannelNonce>;
348 }
349}