#[cfg(not(feature = "std"))]
extern crate alloc;
use crate::endpoint::{Endpoint, EndpointRequest, EndpointResponse};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use codec::{Decode, Encode};
use scale_info::TypeInfo;
pub use sp_domains::{ChainId, ChannelId};
use sp_runtime::app_crypto::sp_core::U256;
use sp_runtime::DispatchError;
use sp_subspace_mmr::ConsensusChainMmrLeafProof;
use sp_trie::StorageProof;
pub type Nonce = U256;
pub type MessageId = (ChannelId, Nonce);
pub type MessageKey = (ChainId, ChannelId, Nonce);
#[derive(Default, Debug, Encode, Decode, Clone, Copy, Eq, PartialEq, TypeInfo)]
pub struct FeeModel<Balance> {
pub relay_fee: Balance,
}
#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub enum ChannelState {
#[default]
Initiated,
Open,
Closed,
}
#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub struct Channel<Balance, AccountId> {
pub channel_id: ChannelId,
pub state: ChannelState,
pub next_inbox_nonce: Nonce,
pub next_outbox_nonce: Nonce,
pub latest_response_received_message_nonce: Option<Nonce>,
pub max_outgoing_messages: u32,
pub fee: FeeModel<Balance>,
pub maybe_owner: Option<AccountId>,
pub channel_reserve_fee: Balance,
}
#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Copy)]
pub struct ChannelOpenParams<Balance> {
pub max_outgoing_messages: u32,
pub fee_model: FeeModel<Balance>,
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub enum ProtocolMessageRequest<Balance> {
ChannelOpen(ChannelOpenParams<Balance>),
ChannelClose,
}
pub type ProtocolMessageResponse = Result<(), DispatchError>;
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub enum RequestResponse<Request, Response> {
Request(Request),
Response(Response),
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub enum Payload<Balance> {
Protocol(RequestResponse<ProtocolMessageRequest<Balance>, ProtocolMessageResponse>),
Endpoint(RequestResponse<EndpointRequest, EndpointResponse>),
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub enum VersionedPayload<Balance> {
V0(Payload<Balance>),
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Default)]
pub enum MessageWeightTag {
ProtocolChannelOpen,
ProtocolChannelClose,
EndpointRequest(Endpoint),
EndpointResponse(Endpoint),
#[default]
None,
}
impl MessageWeightTag {
pub fn outbox<Balance>(outbox_payload: &VersionedPayload<Balance>) -> Self {
match outbox_payload {
VersionedPayload::V0(Payload::Protocol(RequestResponse::Request(
ProtocolMessageRequest::ChannelOpen(_),
))) => MessageWeightTag::ProtocolChannelOpen,
VersionedPayload::V0(Payload::Protocol(RequestResponse::Request(
ProtocolMessageRequest::ChannelClose,
))) => MessageWeightTag::ProtocolChannelClose,
VersionedPayload::V0(Payload::Endpoint(RequestResponse::Request(endpoint_req))) => {
MessageWeightTag::EndpointRequest(endpoint_req.dst_endpoint.clone())
}
_ => MessageWeightTag::None,
}
}
pub fn inbox_response<Balance>(
req_type: MessageWeightTag,
resp_payload: &VersionedPayload<Balance>,
) -> Self {
match (req_type, resp_payload) {
(
MessageWeightTag::ProtocolChannelOpen,
VersionedPayload::V0(Payload::Protocol(RequestResponse::Response(Ok(_)))),
) => MessageWeightTag::ProtocolChannelOpen,
(
MessageWeightTag::EndpointRequest(endpoint),
VersionedPayload::V0(Payload::Endpoint(RequestResponse::Response(_))),
) => MessageWeightTag::EndpointResponse(endpoint),
_ => MessageWeightTag::None,
}
}
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub struct Message<Balance> {
pub src_chain_id: ChainId,
pub dst_chain_id: ChainId,
pub channel_id: ChannelId,
pub nonce: Nonce,
pub payload: VersionedPayload<Balance>,
pub last_delivered_message_response_nonce: Option<Nonce>,
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub enum Proof<CBlockNumber, CBlockHash, MmrHash> {
Consensus {
consensus_chain_mmr_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
message_proof: StorageProof,
},
Domain {
consensus_chain_mmr_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
domain_proof: StorageProof,
message_proof: StorageProof,
},
}
impl<CBlockNumber, CBlockHash, MmrHash> Proof<CBlockNumber, CBlockHash, MmrHash> {
pub fn message_proof(&self) -> StorageProof {
match self {
Proof::Consensus { message_proof, .. } => message_proof.clone(),
Proof::Domain { message_proof, .. } => message_proof.clone(),
}
}
pub fn consensus_mmr_proof(
&self,
) -> ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>
where
CBlockNumber: Clone,
CBlockHash: Clone,
MmrHash: Clone,
{
match self {
Proof::Consensus {
consensus_chain_mmr_proof,
..
} => consensus_chain_mmr_proof.clone(),
Proof::Domain {
consensus_chain_mmr_proof,
..
} => consensus_chain_mmr_proof.clone(),
}
}
pub fn domain_proof(&self) -> Option<StorageProof> {
match self {
Proof::Consensus { .. } => None,
Proof::Domain { domain_proof, .. } => Some(domain_proof.clone()),
}
}
}
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
pub struct CrossDomainMessage<CBlockNumber, CBlockHash, MmrHash> {
pub src_chain_id: ChainId,
pub dst_chain_id: ChainId,
pub channel_id: ChannelId,
pub nonce: Nonce,
pub proof: Proof<CBlockNumber, CBlockHash, MmrHash>,
pub weight_tag: MessageWeightTag,
}
#[derive(Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
pub struct BlockMessageWithStorageKey {
pub src_chain_id: ChainId,
pub dst_chain_id: ChainId,
pub channel_id: ChannelId,
pub nonce: Nonce,
pub storage_key: Vec<u8>,
pub weight_tag: MessageWeightTag,
}
impl BlockMessageWithStorageKey {
pub fn id(&self) -> (ChannelId, Nonce) {
(self.channel_id, self.nonce)
}
}
#[derive(Default, Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)]
pub struct BlockMessagesWithStorageKey {
pub outbox: Vec<BlockMessageWithStorageKey>,
pub inbox_responses: Vec<BlockMessageWithStorageKey>,
}
impl BlockMessagesWithStorageKey {
pub fn is_empty(&self) -> bool {
self.outbox.is_empty() && self.inbox_responses.is_empty()
}
}
impl<BlockNumber, BlockHash, MmrHash> CrossDomainMessage<BlockNumber, BlockHash, MmrHash> {
pub fn from_relayer_msg_with_proof(
r_msg: BlockMessageWithStorageKey,
proof: Proof<BlockNumber, BlockHash, MmrHash>,
) -> Self {
CrossDomainMessage {
src_chain_id: r_msg.src_chain_id,
dst_chain_id: r_msg.dst_chain_id,
channel_id: r_msg.channel_id,
nonce: r_msg.nonce,
proof,
weight_tag: r_msg.weight_tag,
}
}
}