1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright 2021 Centrifuge GmbH (centrifuge.io).
// This file is part of Centrifuge chain project.

// Centrifuge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version (see http://www.gnu.org/licenses).

// Centrifuge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

use frame_support::{dispatch::DispatchResult, weights::Weight};
use sp_runtime::{app_crypto::sp_core::H160, DispatchError};
use sp_std::vec::Vec;

/// Type that represents the hash of an LP message.
pub type MessageHash = [u8; 32];

/// An encoding & decoding trait for the purpose of meeting the
/// LiquidityPools General Message Passing Format
pub trait LpMessageSerializer: Sized {
	/// Serialize the message
	fn serialize(&self) -> Vec<u8>;

	/// Deserialize the message
	fn deserialize(input: &[u8]) -> Result<Self, DispatchError>;
}

/// Behavior or a message that can be batched
pub trait LpMessageBatch: Sized {
	/// Extend this message with a new one
	fn pack_with(&mut self, other: Self) -> DispatchResult;

	/// Decompose the message into a list of messages
	/// If the message is not decomposable, it returns the own message.
	fn submessages(&self) -> Vec<Self>;

	/// Creates an empty message.
	/// It's the identity message for composing messages with pack_with
	fn empty() -> Self;
}

/// Support for hashing
pub trait LpMessageHash {
	/// Retrieves the message hash, if the message is a proof type.
	fn get_message_hash(&self) -> MessageHash;
}

/// Behavior of a message that can support proofs
pub trait LpMessageProof: LpMessageHash {
	/// Returns whether the message is a proof or not.
	fn is_proof_message(&self) -> bool;

	/// Converts the message into a message proof type.
	fn to_proof_message(&self) -> Self;
}

//Behavior of a message that support recovery
pub trait LpMessageRecovery: LpMessageHash {
	/// Creates a message used for initiating message recovery.
	///
	/// Hash - hash of the message that should be recovered.
	/// Router - the address of the recovery router.
	fn initiate_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self;

	/// Creates a message used for disputing message recovery.
	///
	/// Hash - hash of the message that should be disputed.
	/// Router - the address of the recovery router.
	fn dispute_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self;
}

/// Behavior of a message that can be forwarded
pub trait LpMessageForwarded: Sized {
	type Domain;

	/// Checks whether a message is a forwarded one.
	fn is_forwarded(&self) -> bool;

	/// Unwraps a forwarded message.
	fn unwrap_forwarded(self) -> Option<(Self::Domain, H160, Self)>;

	/// Attempts to wrap into a forwarded message.
	fn try_wrap_forward(
		domain: Self::Domain,
		forwarding_contract: H160,
		message: Self,
	) -> Result<Self, DispatchError>;
}

pub trait RouterProvider<Domain>: Sized {
	/// The router identifier.
	type RouterId;

	/// Returns a list of routers supported for the given domain.
	fn routers_for_domain(domain: Domain) -> Vec<Self::RouterId>;
}

/// The behavior of an entity that can send messages
pub trait MessageSender {
	/// The middleware by where this message is sent
	type Middleware;

	/// The originator of the message to be sent
	type Origin;

	/// The type of the message
	type Message;

	/// Sends a message for origin to destination
	fn send(
		middleware: Self::Middleware,
		origin: Self::Origin,
		message: Self::Message,
	) -> DispatchResult;
}

/// The behavior of an entity that can receive messages
pub trait MessageReceiver {
	/// The middleware by where this message is received
	type Middleware;

	/// The originator of the received message
	type Origin;

	type Message;

	/// Sends a message for origin to destination
	fn receive(
		middleware: Self::Middleware,
		origin: Self::Origin,
		message: Self::Message,
	) -> DispatchResult;
}

/// The trait required for queueing messages.
pub trait MessageQueue {
	/// The message type.
	type Message;

	/// Submit a message to the queue.
	fn queue(msg: Self::Message) -> DispatchResult;
}

/// The trait required for processing dequeued messages.
pub trait MessageProcessor {
	/// The message type.
	type Message;

	/// Process a message.
	fn process(msg: Self::Message) -> (DispatchResult, Weight);

	/// Max weight that processing a message can take
	fn max_processing_weight(msg: &Self::Message) -> Weight;
}

/// The trait required for handling outbound LP messages.
pub trait OutboundMessageHandler {
	/// The sender type of the outbound message.
	type Sender;

	/// The destination type of the outbound message.
	type Destination;

	/// The message type.
	type Message;

	/// Handle an outbound message.
	fn handle(
		sender: Self::Sender,
		destination: Self::Destination,
		msg: Self::Message,
	) -> DispatchResult;
}

/// The trait required for handling inbound LP messages.
pub trait InboundMessageHandler {
	/// The sender type of the inbound message.
	type Sender;

	/// The message type.
	type Message;

	/// Handle an inbound message.
	fn handle(sender: Self::Sender, msg: Self::Message) -> DispatchResult;
}