1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4use crate::endpoint::{
5 CollectedFee, Endpoint, EndpointRequest, EndpointRequestWithCollectedFee, EndpointResponse,
6};
7#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9use parity_scale_codec::{Decode, Encode};
10use scale_info::TypeInfo;
11pub use sp_domains::{ChainId, ChannelId};
12use sp_runtime::app_crypto::sp_core::U256;
13use sp_runtime::DispatchError;
14use sp_subspace_mmr::ConsensusChainMmrLeafProof;
15use sp_trie::StorageProof;
16
17pub type Nonce = U256;
20
21pub type MessageId = (ChannelId, Nonce);
23
24pub type MessageKey = (ChainId, ChannelId, Nonce);
26
27#[derive(Default, Debug, Encode, Decode, Clone, Copy, Eq, PartialEq, TypeInfo)]
29pub struct FeeModel<Balance> {
30 pub relay_fee: Balance,
32}
33
34#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
36pub enum ChannelState {
37 #[default]
39 Initiated,
40 Open,
42 Closed,
44}
45
46#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
48pub struct Channel<Balance, AccountId> {
49 pub channel_id: ChannelId,
51 pub state: ChannelState,
53 pub next_inbox_nonce: Nonce,
55 pub next_outbox_nonce: Nonce,
57 pub latest_response_received_message_nonce: Option<Nonce>,
59 pub max_outgoing_messages: u32,
61 pub fee: FeeModel<Balance>,
63 pub maybe_owner: Option<AccountId>,
66 pub channel_reserve_fee: Balance,
68}
69
70#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Copy)]
72pub struct ChannelOpenParams<Balance> {
73 pub max_outgoing_messages: u32,
74 pub fee_model: FeeModel<Balance>,
75}
76
77#[derive(Debug, Encode, Decode, Eq, PartialEq, TypeInfo, Copy, Clone)]
79pub struct ChannelOpenParamsV1 {
80 pub max_outgoing_messages: u32,
81}
82
83#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
85pub enum ProtocolMessageRequest<ChannelOpenParams> {
86 ChannelOpen(ChannelOpenParams),
88 ChannelClose,
90}
91
92impl<Balance: Default> From<ProtocolMessageRequest<ChannelOpenParamsV1>>
93 for ProtocolMessageRequest<ChannelOpenParams<Balance>>
94{
95 fn from(value: ProtocolMessageRequest<ChannelOpenParamsV1>) -> Self {
96 match value {
97 ProtocolMessageRequest::ChannelOpen(params) => {
98 ProtocolMessageRequest::ChannelOpen(ChannelOpenParams {
99 max_outgoing_messages: params.max_outgoing_messages,
100 fee_model: FeeModel::default(),
102 })
103 }
104 ProtocolMessageRequest::ChannelClose => ProtocolMessageRequest::ChannelClose,
105 }
106 }
107}
108
109impl<Balance: Default> From<ProtocolMessageRequest<ChannelOpenParams<Balance>>>
110 for ProtocolMessageRequest<ChannelOpenParamsV1>
111{
112 fn from(value: ProtocolMessageRequest<ChannelOpenParams<Balance>>) -> Self {
113 match value {
114 ProtocolMessageRequest::ChannelOpen(params) => {
115 ProtocolMessageRequest::ChannelOpen(ChannelOpenParamsV1 {
116 max_outgoing_messages: params.max_outgoing_messages,
117 })
118 }
119 ProtocolMessageRequest::ChannelClose => ProtocolMessageRequest::ChannelClose,
120 }
121 }
122}
123
124pub type ProtocolMessageResponse = Result<(), DispatchError>;
126
127#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
129pub enum RequestResponse<Request, Response> {
130 Request(Request),
131 Response(Response),
132}
133
134#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
136pub enum Payload<Balance> {
137 Protocol(
139 RequestResponse<
140 ProtocolMessageRequest<ChannelOpenParams<Balance>>,
141 ProtocolMessageResponse,
142 >,
143 ),
144 Endpoint(RequestResponse<EndpointRequest, EndpointResponse>),
146}
147
148impl<Balance: Default> From<PayloadV1<Balance>> for Payload<Balance> {
149 fn from(value: PayloadV1<Balance>) -> Self {
150 match value {
151 PayloadV1::Protocol(RequestResponse::Request(req)) => {
152 Payload::Protocol(RequestResponse::Request(req.into()))
153 }
154 PayloadV1::Protocol(RequestResponse::Response(resp)) => {
155 Payload::Protocol(RequestResponse::Response(resp))
156 }
157 PayloadV1::Endpoint(RequestResponse::Request(req)) => {
158 Payload::Endpoint(RequestResponse::Request(req.into()))
159 }
160 PayloadV1::Endpoint(RequestResponse::Response(resp)) => {
161 Payload::Endpoint(RequestResponse::Response(resp))
162 }
163 }
164 }
165}
166
167#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
169pub enum PayloadV1<Balance> {
170 Protocol(RequestResponse<ProtocolMessageRequest<ChannelOpenParamsV1>, ProtocolMessageResponse>),
172 Endpoint(RequestResponse<EndpointRequestWithCollectedFee<Balance>, EndpointResponse>),
174}
175
176impl<Balance: Default> From<Payload<Balance>> for PayloadV1<Balance> {
177 fn from(value: Payload<Balance>) -> Self {
178 match value {
179 Payload::Protocol(RequestResponse::Request(req)) => {
180 PayloadV1::Protocol(RequestResponse::Request(req.into()))
181 }
182 Payload::Protocol(RequestResponse::Response(resp)) => {
183 PayloadV1::Protocol(RequestResponse::Response(resp))
184 }
185 Payload::Endpoint(RequestResponse::Request(req)) => {
186 PayloadV1::Endpoint(RequestResponse::Request(req.into()))
187 }
188 Payload::Endpoint(RequestResponse::Response(resp)) => {
189 PayloadV1::Endpoint(RequestResponse::Response(resp))
190 }
191 }
192 }
193}
194
195#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
197pub enum VersionedPayload<Balance> {
198 #[codec(index = 0)]
199 V0(Payload<Balance>),
200 #[codec(index = 1)]
201 V1(PayloadV1<Balance>),
202}
203
204#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
205pub struct ConvertedPayload<Balance> {
206 pub payload: Payload<Balance>,
207 pub is_v1: bool,
208}
209
210impl<Balance> From<Payload<Balance>> for ConvertedPayload<Balance> {
211 fn from(value: Payload<Balance>) -> Self {
212 ConvertedPayload {
213 payload: value,
214 is_v1: false,
215 }
216 }
217}
218
219impl<Balance: Default> From<PayloadV1<Balance>> for ConvertedPayload<Balance> {
220 fn from(value: PayloadV1<Balance>) -> Self {
221 ConvertedPayload {
222 payload: value.into(),
223 is_v1: true,
224 }
225 }
226}
227
228impl<Balance: Default + Clone> VersionedPayload<Balance> {
229 pub fn into_payload_v0(self) -> ConvertedPayload<Balance> {
230 match self {
231 VersionedPayload::V0(payload) => payload.into(),
232 VersionedPayload::V1(payload) => payload.into(),
233 }
234 }
235
236 pub fn maybe_collected_fee(&self) -> Option<CollectedFee<Balance>> {
237 match self {
238 VersionedPayload::V1(PayloadV1::Endpoint(RequestResponse::Request(req))) => {
240 Some(req.collected_fee.clone())
241 }
242 _ => None,
243 }
244 }
245}
246
247#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Default)]
249pub enum MessageWeightTag {
250 ProtocolChannelOpen,
251 ProtocolChannelClose,
252 EndpointRequest(Endpoint),
253 EndpointResponse(Endpoint),
254 #[default]
255 None,
256}
257
258impl MessageWeightTag {
259 pub fn outbox<Balance>(outbox_payload: &VersionedPayload<Balance>) -> Self {
261 match outbox_payload {
262 VersionedPayload::V0(Payload::Protocol(RequestResponse::Request(
263 ProtocolMessageRequest::ChannelOpen(_),
264 )))
265 | VersionedPayload::V1(PayloadV1::Protocol(RequestResponse::Request(
266 ProtocolMessageRequest::ChannelOpen(_),
267 ))) => MessageWeightTag::ProtocolChannelOpen,
268 VersionedPayload::V0(Payload::Protocol(RequestResponse::Request(
269 ProtocolMessageRequest::ChannelClose,
270 )))
271 | VersionedPayload::V1(PayloadV1::Protocol(RequestResponse::Request(
272 ProtocolMessageRequest::ChannelClose,
273 ))) => MessageWeightTag::ProtocolChannelClose,
274 VersionedPayload::V0(Payload::Endpoint(RequestResponse::Request(req)))
275 | VersionedPayload::V1(PayloadV1::Endpoint(RequestResponse::Request(
276 EndpointRequestWithCollectedFee { req, .. },
277 ))) => MessageWeightTag::EndpointRequest(req.dst_endpoint.clone()),
278 _ => MessageWeightTag::None,
279 }
280 }
281
282 pub fn inbox_response<Balance>(
285 req_type: MessageWeightTag,
286 resp_payload: &VersionedPayload<Balance>,
287 ) -> Self {
288 match (req_type, resp_payload) {
289 (
290 MessageWeightTag::ProtocolChannelOpen,
291 VersionedPayload::V0(Payload::Protocol(RequestResponse::Response(Ok(_)))),
292 ) => MessageWeightTag::ProtocolChannelOpen,
293 (
294 MessageWeightTag::EndpointRequest(endpoint),
295 VersionedPayload::V0(Payload::Endpoint(RequestResponse::Response(_))),
296 ) => MessageWeightTag::EndpointResponse(endpoint),
297 (
298 MessageWeightTag::ProtocolChannelOpen,
299 VersionedPayload::V1(PayloadV1::Protocol(RequestResponse::Response(Ok(_)))),
300 ) => MessageWeightTag::ProtocolChannelOpen,
301 (
302 MessageWeightTag::EndpointRequest(endpoint),
303 VersionedPayload::V1(PayloadV1::Endpoint(RequestResponse::Response(_))),
304 ) => MessageWeightTag::EndpointResponse(endpoint),
305 _ => MessageWeightTag::None,
306 }
307 }
308}
309
310#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
312pub struct Message<Balance> {
313 pub src_chain_id: ChainId,
315 pub dst_chain_id: ChainId,
317 pub channel_id: ChannelId,
319 pub nonce: Nonce,
321 pub payload: VersionedPayload<Balance>,
323 pub last_delivered_message_response_nonce: Option<Nonce>,
325}
326
327#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
328pub enum Proof<CBlockNumber, CBlockHash, MmrHash> {
329 Consensus {
330 consensus_chain_mmr_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
332 message_proof: StorageProof,
334 },
335 Domain {
336 consensus_chain_mmr_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
338 domain_proof: StorageProof,
340 message_proof: StorageProof,
342 },
343}
344
345impl<CBlockNumber, CBlockHash, MmrHash> Proof<CBlockNumber, CBlockHash, MmrHash> {
346 pub fn message_proof(&self) -> StorageProof {
347 match self {
348 Proof::Consensus { message_proof, .. } => message_proof.clone(),
349 Proof::Domain { message_proof, .. } => message_proof.clone(),
350 }
351 }
352
353 pub fn consensus_mmr_proof(
354 &self,
355 ) -> ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>
356 where
357 CBlockNumber: Clone,
358 CBlockHash: Clone,
359 MmrHash: Clone,
360 {
361 match self {
362 Proof::Consensus {
363 consensus_chain_mmr_proof,
364 ..
365 } => consensus_chain_mmr_proof.clone(),
366 Proof::Domain {
367 consensus_chain_mmr_proof,
368 ..
369 } => consensus_chain_mmr_proof.clone(),
370 }
371 }
372
373 pub fn domain_proof(&self) -> Option<StorageProof> {
374 match self {
375 Proof::Consensus { .. } => None,
376 Proof::Domain { domain_proof, .. } => Some(domain_proof.clone()),
377 }
378 }
379}
380
381#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
383pub struct CrossDomainMessage<CBlockNumber, CBlockHash, MmrHash> {
384 pub src_chain_id: ChainId,
386 pub dst_chain_id: ChainId,
388 pub channel_id: ChannelId,
390 pub nonce: Nonce,
392 pub proof: Proof<CBlockNumber, CBlockHash, MmrHash>,
394 pub weight_tag: MessageWeightTag,
396}
397
398#[derive(Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
400pub struct BlockMessageWithStorageKey {
401 pub src_chain_id: ChainId,
403 pub dst_chain_id: ChainId,
405 pub channel_id: ChannelId,
407 pub nonce: Nonce,
409 pub storage_key: Vec<u8>,
411 pub weight_tag: MessageWeightTag,
413}
414
415impl BlockMessageWithStorageKey {
416 pub fn id(&self) -> (ChannelId, Nonce) {
417 (self.channel_id, self.nonce)
418 }
419}
420
421#[derive(Default, Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
423pub struct BlockMessagesWithStorageKey {
424 pub outbox: Vec<BlockMessageWithStorageKey>,
425 pub inbox_responses: Vec<BlockMessageWithStorageKey>,
426}
427
428impl BlockMessagesWithStorageKey {
429 pub fn is_empty(&self) -> bool {
430 self.outbox.is_empty() && self.inbox_responses.is_empty()
431 }
432}
433
434impl<BlockNumber, BlockHash, MmrHash> CrossDomainMessage<BlockNumber, BlockHash, MmrHash> {
435 pub fn from_relayer_msg_with_proof(
436 r_msg: BlockMessageWithStorageKey,
437 proof: Proof<BlockNumber, BlockHash, MmrHash>,
438 ) -> Self {
439 CrossDomainMessage {
440 src_chain_id: r_msg.src_chain_id,
441 dst_chain_id: r_msg.dst_chain_id,
442 channel_id: r_msg.channel_id,
443 nonce: r_msg.nonce,
444 proof,
445 weight_tag: r_msg.weight_tag,
446 }
447 }
448}