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::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};
36use messages::{BlockMessagesWithStorageKey, ChannelId, CrossDomainMessage, MessageId};
37use parity_scale_codec::{Decode, Encode};
38use scale_info::TypeInfo;
39use sp_domains::{ChainId, DomainAllowlistUpdates, DomainId};
40use sp_subspace_mmr::ConsensusChainMmrLeafProof;
41#[cfg(feature = "std")]
42use std::collections::BTreeMap;
43#[cfg(feature = "std")]
44use std::collections::BTreeSet;
45
46pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"messengr";
48
49pub const MAX_FUTURE_ALLOWED_NONCES: u32 = 256;
58
59pub trait OnXDMRewards<Balance> {
61 fn on_xdm_rewards(rewards: Balance);
62 fn on_chain_protocol_fees(chain_id: ChainId, fees: Balance);
63}
64
65pub trait NoteChainTransfer<Balance> {
67 fn note_transfer_in(amount: Balance, from_chain_id: ChainId) -> bool;
68 fn note_transfer_out(amount: Balance, to_chain_id: ChainId) -> bool;
69}
70
71impl<Balance> NoteChainTransfer<Balance> for () {
72 fn note_transfer_in(_amount: Balance, _from_chain_id: ChainId) -> bool {
73 true
74 }
75 fn note_transfer_out(_amount: Balance, _to_chain_id: ChainId) -> bool {
76 true
77 }
78}
79
80impl<Balance> OnXDMRewards<Balance> for () {
81 fn on_xdm_rewards(_: Balance) {}
82
83 fn on_chain_protocol_fees(_chain_id: ChainId, _fees: Balance) {}
84}
85
86pub trait DomainRegistration {
88 fn is_domain_registered(domain_id: DomainId) -> bool;
89}
90
91impl DomainRegistration for () {
92 fn is_domain_registered(_domain_id: DomainId) -> bool {
93 false
94 }
95}
96
97pub trait StorageKeys {
99 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option<Vec<u8>>;
101
102 fn outbox_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>>;
104
105 fn inbox_responses_storage_key(chain_id: ChainId, message_key: MessageKey) -> Option<Vec<u8>>;
107}
108
109impl StorageKeys for () {
110 fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Option<Vec<u8>> {
111 None
112 }
113
114 fn outbox_storage_key(_chain_id: ChainId, _message_key: MessageKey) -> Option<Vec<u8>> {
115 None
116 }
117
118 fn inbox_responses_storage_key(
119 _chain_id: ChainId,
120 _message_key: MessageKey,
121 ) -> Option<Vec<u8>> {
122 None
123 }
124}
125
126#[derive(Debug, Encode, Decode)]
128pub struct InherentType {
129 pub maybe_updates: Option<DomainAllowlistUpdates>,
130}
131
132#[derive(Debug, Encode)]
134#[cfg_attr(feature = "std", derive(Decode))]
135pub enum InherentError {
136 MissingAllowlistUpdates,
137 IncorrectAllowlistUpdates,
138}
139
140impl IsFatalError for InherentError {
141 fn is_fatal_error(&self) -> bool {
142 true
143 }
144}
145
146#[cfg(feature = "std")]
148pub struct InherentDataProvider {
149 data: InherentType,
150}
151
152#[cfg(feature = "std")]
153impl InherentDataProvider {
154 pub fn new(data: InherentType) -> Self {
156 Self { data }
157 }
158
159 pub fn data(&self) -> &InherentType {
161 &self.data
162 }
163}
164
165#[cfg(feature = "std")]
166#[async_trait::async_trait]
167impl sp_inherents::InherentDataProvider for InherentDataProvider {
168 async fn provide_inherent_data(
169 &self,
170 inherent_data: &mut InherentData,
171 ) -> Result<(), sp_inherents::Error> {
172 inherent_data.put_data(INHERENT_IDENTIFIER, &self.data)
173 }
174
175 async fn try_handle_error(
176 &self,
177 identifier: &InherentIdentifier,
178 error: &[u8],
179 ) -> Option<Result<(), sp_inherents::Error>> {
180 if *identifier != INHERENT_IDENTIFIER {
181 return None;
182 }
183
184 let error = InherentError::decode(&mut &*error).ok()?;
185
186 Some(Err(sp_inherents::Error::Application(Box::from(format!(
187 "{error:?}"
188 )))))
189 }
190}
191
192#[derive(Debug, Encode, Decode, TypeInfo, Copy, Clone)]
194pub enum XdmId {
195 RelayMessage(MessageKey),
196 RelayResponseMessage(MessageKey),
197}
198
199impl XdmId {
200 pub fn get_chain_id_and_channel_id(&self) -> (ChainId, ChannelId) {
201 match self {
202 XdmId::RelayMessage(key) => (key.0, key.1),
203 XdmId::RelayResponseMessage(key) => (key.0, key.1),
204 }
205 }
206}
207
208#[derive(Debug, Encode, Decode, TypeInfo, Copy, Clone)]
209pub struct ChannelNonce {
210 pub relay_msg_nonce: Option<Nonce>,
213 pub relay_response_msg_nonce: Option<Nonce>,
216}
217
218sp_api::decl_runtime_apis! {
219 #[api_version(2)]
221 pub trait RelayerApi<BlockNumber, CNumber, CHash>
222 where
223 BlockNumber: Encode + Decode,
224 CNumber: Encode + Decode,
225 CHash: Encode + Decode,
226 {
227 fn block_messages() -> BlockMessagesWithStorageKey;
230
231 fn outbox_message_unsigned(
233 msg: CrossDomainMessage<CNumber, CHash, sp_core::H256>,
234 ) -> Option<Block::Extrinsic>;
235
236 fn inbox_response_message_unsigned(
238 msg: CrossDomainMessage<CNumber, CHash, sp_core::H256>,
239 ) -> Option<Block::Extrinsic>;
240
241 fn should_relay_outbox_message(dst_chain_id: ChainId, msg_id: MessageId) -> bool;
243
244 fn should_relay_inbox_message_response(dst_chain_id: ChainId, msg_id: MessageId) -> bool;
246
247 fn updated_channels() -> BTreeSet<(ChainId, ChannelId)>;
249
250 fn channel_storage_key(chain_id: ChainId, channel_id: ChannelId) -> Vec<u8>;
252
253 fn open_channels() -> BTreeSet<(ChainId, ChannelId)>;
255 }
256
257 #[api_version(3)]
259 pub trait MessengerApi<CNumber, CHash>
260 where
261 CNumber: Encode + Decode,
262 CHash: Encode + Decode,
263 {
264 fn is_xdm_mmr_proof_valid(
267 ext: &Block::Extrinsic
268 ) -> Option<bool>;
269
270 fn extract_xdm_mmr_proof(ext: &Block::Extrinsic) -> Option<ConsensusChainMmrLeafProof<CNumber, CHash, sp_core::H256>>;
272
273 #[allow(clippy::ptr_arg)]
277 fn batch_extract_xdm_mmr_proof(ext: &Vec<Block::Extrinsic>) -> BTreeMap<u32, ConsensusChainMmrLeafProof<CNumber, CHash, sp_core::H256>>;
278
279 fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec<u8>;
281
282 fn outbox_storage_key(message_key: MessageKey) -> Vec<u8>;
284
285 fn inbox_response_storage_key(message_key: MessageKey) -> Vec<u8>;
287
288 fn domain_chains_allowlist_update(domain_id: DomainId) -> Option<DomainAllowlistUpdates>;
290
291 fn xdm_id(ext: &Block::Extrinsic) -> Option<XdmId>;
293
294 fn channel_nonce(chain_id: ChainId, channel_id: ChannelId) -> Option<ChannelNonce>;
296 }
297}