1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4use crate::endpoint::{Endpoint, EndpointRequestWithCollectedFee, EndpointResponse};
5#[cfg(not(feature = "std"))]
6use alloc::vec::Vec;
7use parity_scale_codec::{Decode, Encode};
8use scale_info::TypeInfo;
9pub use sp_domains::{ChainId, ChannelId};
10use sp_runtime::app_crypto::sp_core::U256;
11use sp_runtime::DispatchError;
12use sp_subspace_mmr::ConsensusChainMmrLeafProof;
13use sp_trie::StorageProof;
14
15pub type Nonce = U256;
18
19pub type MessageId = (ChannelId, Nonce);
21
22pub type MessageKey = (ChainId, ChannelId, Nonce);
24
25#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
27pub enum ChannelState {
28 #[default]
30 Initiated,
31 Open,
33 Closed,
35}
36
37#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
39pub enum ChannelStateWithNonce {
40 #[default]
42 Initiated,
43 Open,
45 Closed {
47 next_outbox_nonce: Nonce,
48 next_inbox_nonce: Nonce,
49 },
50}
51
52#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
54pub struct Channel<Balance, AccountId> {
55 pub channel_id: ChannelId,
57 pub state: ChannelState,
59 pub next_inbox_nonce: Nonce,
61 pub next_outbox_nonce: Nonce,
63 pub latest_response_received_message_nonce: Option<Nonce>,
65 pub max_outgoing_messages: u32,
67 pub maybe_owner: Option<AccountId>,
70 pub channel_reserve_fee: Balance,
72}
73
74#[derive(Debug, Encode, Decode, Eq, PartialEq, TypeInfo, Copy, Clone)]
76pub struct ChannelOpenParamsV1 {
77 pub max_outgoing_messages: u32,
78}
79
80#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
82pub enum ProtocolMessageRequest<ChannelOpenParams> {
83 ChannelOpen(ChannelOpenParams),
85 ChannelClose,
87}
88
89pub type ProtocolMessageResponse = Result<(), DispatchError>;
91
92#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
94pub enum RequestResponse<Request, Response> {
95 Request(Request),
96 Response(Response),
97}
98
99#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
101pub enum PayloadV1<Balance> {
102 Protocol(RequestResponse<ProtocolMessageRequest<ChannelOpenParamsV1>, ProtocolMessageResponse>),
104 Endpoint(RequestResponse<EndpointRequestWithCollectedFee<Balance>, EndpointResponse>),
106}
107
108#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
110pub enum VersionedPayload<Balance> {
111 #[codec(index = 1)]
112 V1(PayloadV1<Balance>),
113}
114
115#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Default)]
117pub enum MessageWeightTag {
118 ProtocolChannelOpen,
119 ProtocolChannelClose,
120 EndpointRequest(Endpoint),
121 EndpointResponse(Endpoint),
122 #[default]
123 None,
124}
125
126impl MessageWeightTag {
127 pub fn outbox<Balance>(outbox_payload: &VersionedPayload<Balance>) -> Self {
129 match outbox_payload {
130 VersionedPayload::V1(PayloadV1::Protocol(RequestResponse::Request(
131 ProtocolMessageRequest::ChannelOpen(_),
132 ))) => MessageWeightTag::ProtocolChannelOpen,
133 VersionedPayload::V1(PayloadV1::Protocol(RequestResponse::Request(
134 ProtocolMessageRequest::ChannelClose,
135 ))) => MessageWeightTag::ProtocolChannelClose,
136 VersionedPayload::V1(PayloadV1::Endpoint(RequestResponse::Request(
137 EndpointRequestWithCollectedFee { req, .. },
138 ))) => MessageWeightTag::EndpointRequest(req.dst_endpoint.clone()),
139 _ => MessageWeightTag::None,
140 }
141 }
142
143 pub fn inbox_response<Balance>(
146 req_type: MessageWeightTag,
147 resp_payload: &VersionedPayload<Balance>,
148 ) -> Self {
149 match (req_type, resp_payload) {
150 (
151 MessageWeightTag::ProtocolChannelOpen,
152 VersionedPayload::V1(PayloadV1::Protocol(RequestResponse::Response(Ok(_)))),
153 ) => MessageWeightTag::ProtocolChannelOpen,
154 (
155 MessageWeightTag::EndpointRequest(endpoint),
156 VersionedPayload::V1(PayloadV1::Endpoint(RequestResponse::Response(_))),
157 ) => MessageWeightTag::EndpointResponse(endpoint),
158 _ => MessageWeightTag::None,
159 }
160 }
161}
162
163#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
165pub struct Message<Balance> {
166 pub src_chain_id: ChainId,
168 pub dst_chain_id: ChainId,
170 pub channel_id: ChannelId,
172 pub nonce: Nonce,
174 pub payload: VersionedPayload<Balance>,
176 pub last_delivered_message_response_nonce: Option<Nonce>,
178}
179
180#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
181pub enum Proof<CBlockNumber, CBlockHash, MmrHash> {
182 Consensus {
183 consensus_chain_mmr_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
185 message_proof: StorageProof,
187 },
188 Domain {
189 consensus_chain_mmr_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
191 domain_proof: StorageProof,
193 message_proof: StorageProof,
195 },
196}
197
198impl<CBlockNumber, CBlockHash, MmrHash> Proof<CBlockNumber, CBlockHash, MmrHash> {
199 pub fn message_proof(&self) -> StorageProof {
200 match self {
201 Proof::Consensus { message_proof, .. } => message_proof.clone(),
202 Proof::Domain { message_proof, .. } => message_proof.clone(),
203 }
204 }
205
206 pub fn consensus_mmr_proof(
207 &self,
208 ) -> ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>
209 where
210 CBlockNumber: Clone,
211 CBlockHash: Clone,
212 MmrHash: Clone,
213 {
214 match self {
215 Proof::Consensus {
216 consensus_chain_mmr_proof,
217 ..
218 } => consensus_chain_mmr_proof.clone(),
219 Proof::Domain {
220 consensus_chain_mmr_proof,
221 ..
222 } => consensus_chain_mmr_proof.clone(),
223 }
224 }
225
226 pub fn domain_proof(&self) -> Option<StorageProof> {
227 match self {
228 Proof::Consensus { .. } => None,
229 Proof::Domain { domain_proof, .. } => Some(domain_proof.clone()),
230 }
231 }
232}
233
234#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
236pub struct CrossDomainMessage<CBlockNumber, CBlockHash, MmrHash> {
237 pub src_chain_id: ChainId,
239 pub dst_chain_id: ChainId,
241 pub channel_id: ChannelId,
243 pub nonce: Nonce,
245 pub proof: Proof<CBlockNumber, CBlockHash, MmrHash>,
247 pub weight_tag: MessageWeightTag,
249}
250
251#[derive(Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
253pub struct BlockMessageWithStorageKey {
254 pub src_chain_id: ChainId,
256 pub dst_chain_id: ChainId,
258 pub channel_id: ChannelId,
260 pub nonce: Nonce,
262 pub storage_key: Vec<u8>,
264 pub weight_tag: MessageWeightTag,
266}
267
268impl BlockMessageWithStorageKey {
269 pub fn id(&self) -> (ChannelId, Nonce) {
270 (self.channel_id, self.nonce)
271 }
272}
273
274#[derive(Default, Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
276pub struct BlockMessagesWithStorageKey {
277 pub outbox: Vec<BlockMessageWithStorageKey>,
278 pub inbox_responses: Vec<BlockMessageWithStorageKey>,
279}
280
281impl BlockMessagesWithStorageKey {
282 pub fn is_empty(&self) -> bool {
283 self.outbox.is_empty() && self.inbox_responses.is_empty()
284 }
285}
286
287#[derive(Default, Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
289pub struct MessagesWithStorageKey {
290 pub outbox: Vec<MessageNonceWithStorageKey>,
291 pub inbox_responses: Vec<MessageNonceWithStorageKey>,
292}
293
294#[derive(Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
296pub struct MessageNonceWithStorageKey {
297 pub nonce: Nonce,
299 pub storage_key: Vec<u8>,
301 pub weight_tag: MessageWeightTag,
303}
304
305#[derive(Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
307pub struct BlockMessagesQuery {
308 pub chain_id: ChainId,
309 pub channel_id: ChannelId,
310 pub outbox_from: Nonce,
311 pub inbox_responses_from: Nonce,
312}
313
314impl<BlockNumber, BlockHash, MmrHash> CrossDomainMessage<BlockNumber, BlockHash, MmrHash> {
315 pub fn from_relayer_msg_with_proof(
316 src_chain_id: ChainId,
317 dst_chain_id: ChainId,
318 channel_id: ChannelId,
319 msg: MessageNonceWithStorageKey,
320 proof: Proof<BlockNumber, BlockHash, MmrHash>,
321 ) -> Self {
322 CrossDomainMessage {
323 src_chain_id,
324 dst_chain_id,
325 channel_id,
326 nonce: msg.nonce,
327 proof,
328 weight_tag: msg.weight_tag,
329 }
330 }
331}