1use crate::pallet::Call as MessengerCall;
4use crate::{
5 Call, Config, Origin, Pallet as Messenger, ValidatedRelayMessage, XDM_TRANSACTION_LONGEVITY,
6};
7use core::cmp::Ordering;
8use frame_support::pallet_prelude::{PhantomData, TypeInfo};
9use frame_support::RuntimeDebugNoBound;
10use frame_system::pallet_prelude::RuntimeCallFor;
11use parity_scale_codec::{Decode, Encode};
12use scale_info::prelude::fmt;
13use sp_messenger::messages::{Message, Nonce};
14use sp_messenger::MAX_FUTURE_ALLOWED_NONCES;
15use sp_runtime::impl_tx_ext_default;
16use sp_runtime::traits::{
17 AsSystemOriginSigner, DispatchInfoOf, DispatchOriginOf, Dispatchable, Implication,
18 TransactionExtension, ValidateResult,
19};
20use sp_runtime::transaction_validity::{
21 InvalidTransaction, TransactionSource, TransactionValidityError, ValidTransaction,
22 ValidTransactionBuilder,
23};
24use sp_subspace_mmr::MmrProofVerifier;
25
26pub trait MaybeMessengerCall<Runtime>
28where
29 Runtime: Config,
30{
31 fn maybe_messenger_call(&self) -> Option<&MessengerCall<Runtime>>;
32}
33
34#[derive(RuntimeDebugNoBound)]
36pub enum Val<T: Config + fmt::Debug> {
37 None,
39 ValidatedRelayMessage(ValidatedRelayMessage<T>),
41}
42
43#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
45pub struct MessengerExtension<Runtime>(PhantomData<Runtime>);
46
47impl<Runtime> MessengerExtension<Runtime> {
48 pub fn new() -> Self {
49 Self(PhantomData)
50 }
51}
52
53impl<Runtime> Default for MessengerExtension<Runtime> {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl<T: Config> fmt::Debug for MessengerExtension<T> {
60 #[cfg(feature = "std")]
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 write!(f, "MessengerExtension",)
63 }
64
65 #[cfg(not(feature = "std"))]
66 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
67 Ok(())
68 }
69}
70
71impl<Runtime> MessengerExtension<Runtime>
72where
73 Runtime: Config + scale_info::TypeInfo + fmt::Debug + Send + Sync,
74{
75 fn check_future_nonce_and_add_requires(
76 mut valid_tx_builder: ValidTransactionBuilder,
77 validated_relay_message: &ValidatedRelayMessage<Runtime>,
78 ) -> Result<ValidTransactionBuilder, TransactionValidityError> {
79 let Message {
80 dst_chain_id,
81 channel_id,
82 nonce: msg_nonce,
83 ..
84 } = &validated_relay_message.message;
85
86 let next_nonce = validated_relay_message.next_nonce;
87 if *msg_nonce > next_nonce {
89 let max_future_nonce = next_nonce.saturating_add(MAX_FUTURE_ALLOWED_NONCES.into());
90 if *msg_nonce > max_future_nonce {
91 return Err(InvalidTransaction::Custom(
92 crate::verification_errors::IN_FUTURE_NONCE,
93 )
94 .into());
95 }
96
97 valid_tx_builder =
98 valid_tx_builder.and_requires((dst_chain_id, channel_id, msg_nonce - Nonce::one()));
99 };
100
101 Ok(valid_tx_builder)
102 }
103
104 fn do_validate(
105 call: &MessengerCall<Runtime>,
106 ) -> Result<(ValidTransaction, ValidatedRelayMessage<Runtime>), TransactionValidityError> {
107 match call {
108 Call::relay_message { msg: xdm } => {
109 let consensus_state_root =
110 Runtime::MmrProofVerifier::verify_proof_and_extract_leaf(
111 xdm.proof.consensus_mmr_proof(),
112 )
113 .ok_or(InvalidTransaction::BadProof)?
114 .state_root();
115
116 let validated_message =
117 Messenger::<Runtime>::validate_relay_message(xdm, consensus_state_root)?;
118
119 let Message {
120 dst_chain_id,
121 channel_id,
122 nonce: msg_nonce,
123 ..
124 } = &validated_message.message;
125
126 let valid_tx_builder = Self::check_future_nonce_and_add_requires(
127 ValidTransaction::with_tag_prefix("MessengerInbox"),
128 &validated_message,
129 )?;
130
131 let validity = valid_tx_builder
132 .priority(1)
135 .longevity(XDM_TRANSACTION_LONGEVITY)
136 .and_provides((dst_chain_id, channel_id, msg_nonce))
137 .propagate(true)
138 .build()?;
139
140 Ok((validity, validated_message))
141 }
142 Call::relay_message_response { msg: xdm } => {
143 let consensus_state_root =
144 Runtime::MmrProofVerifier::verify_proof_and_extract_leaf(
145 xdm.proof.consensus_mmr_proof(),
146 )
147 .ok_or(InvalidTransaction::BadProof)?
148 .state_root();
149
150 let validated_message = Messenger::<Runtime>::validate_relay_message_response(
151 xdm,
152 consensus_state_root,
153 )?;
154
155 let Message {
156 dst_chain_id,
157 channel_id,
158 nonce: msg_nonce,
159 ..
160 } = &validated_message.message;
161
162 let valid_tx_builder = Self::check_future_nonce_and_add_requires(
163 ValidTransaction::with_tag_prefix("MessengerOutboxResponse"),
164 &validated_message,
165 )?;
166
167 let validity = valid_tx_builder
168 .priority(1)
171 .longevity(XDM_TRANSACTION_LONGEVITY)
172 .and_provides((dst_chain_id, channel_id, msg_nonce))
173 .propagate(true)
174 .build()?;
175
176 Ok((validity, validated_message))
177 }
178 _ => Err(InvalidTransaction::Call.into()),
179 }
180 }
181
182 fn do_prepare(
183 call: &MessengerCall<Runtime>,
184 val: ValidatedRelayMessage<Runtime>,
185 ) -> Result<(), TransactionValidityError> {
186 let ValidatedRelayMessage {
187 message,
188 should_init_channel,
189 next_nonce,
190 } = val;
191
192 if message.nonce.cmp(&next_nonce) == Ordering::Greater {
194 return Err(InvalidTransaction::Future.into());
195 }
196
197 match call {
198 Call::relay_message { .. } => {
199 Messenger::<Runtime>::pre_dispatch_relay_message(message, should_init_channel)
200 }
201 Call::relay_message_response { .. } => {
202 Messenger::<Runtime>::pre_dispatch_relay_message_response(message)
203 }
204 _ => Err(InvalidTransaction::Call.into()),
205 }
206 }
207}
208
209impl<Runtime> TransactionExtension<RuntimeCallFor<Runtime>> for MessengerExtension<Runtime>
210where
211 Runtime: Config + scale_info::TypeInfo + fmt::Debug + Send + Sync,
212 <RuntimeCallFor<Runtime> as Dispatchable>::RuntimeOrigin:
213 AsSystemOriginSigner<<Runtime as frame_system::Config>::AccountId> + From<Origin> + Clone,
214 RuntimeCallFor<Runtime>: MaybeMessengerCall<Runtime>,
215{
216 const IDENTIFIER: &'static str = "MessengerExtension";
217 type Implicit = ();
218 type Val = Val<Runtime>;
219 type Pre = ();
220
221 fn validate(
222 &self,
223 origin: DispatchOriginOf<RuntimeCallFor<Runtime>>,
224 call: &RuntimeCallFor<Runtime>,
225 _info: &DispatchInfoOf<RuntimeCallFor<Runtime>>,
226 _len: usize,
227 _self_implicit: Self::Implicit,
228 _inherited_implication: &impl Implication,
229 _source: TransactionSource,
230 ) -> ValidateResult<Self::Val, RuntimeCallFor<Runtime>> {
231 if origin.as_system_origin_signer().is_some() {
233 return Ok((ValidTransaction::default(), Val::None, origin));
234 };
235
236 let messenger_call = match call.maybe_messenger_call() {
237 Some(messenger_call) => messenger_call,
238 None => return Ok((ValidTransaction::default(), Val::None, origin)),
239 };
240
241 let (validity, validated_relay_message) = Self::do_validate(messenger_call)?;
242 Ok((
243 validity,
244 Val::ValidatedRelayMessage(validated_relay_message),
245 Origin::ValidatedUnsigned.into(),
246 ))
247 }
248
249 fn prepare(
250 self,
251 val: Self::Val,
252 _origin: &DispatchOriginOf<RuntimeCallFor<Runtime>>,
253 call: &RuntimeCallFor<Runtime>,
254 _info: &DispatchInfoOf<RuntimeCallFor<Runtime>>,
255 _len: usize,
256 ) -> Result<Self::Pre, TransactionValidityError> {
257 match (call.maybe_messenger_call(), val) {
258 (Some(messenger_call), Val::ValidatedRelayMessage(validated_relay_message)) => {
260 Self::do_prepare(messenger_call, validated_relay_message)
261 }
262 (_, _) => Ok(()),
264 }
265 }
266
267 impl_tx_ext_default!(RuntimeCallFor<Runtime>; weight);
269}
270
271#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
273pub struct MessengerTrustedMmrExtension<Runtime>(PhantomData<Runtime>);
274
275impl<Runtime> MessengerTrustedMmrExtension<Runtime> {
276 pub fn new() -> Self {
277 Self(PhantomData)
278 }
279}
280
281impl<Runtime> Default for MessengerTrustedMmrExtension<Runtime> {
282 fn default() -> Self {
283 Self::new()
284 }
285}
286
287impl<T: Config> fmt::Debug for MessengerTrustedMmrExtension<T> {
288 #[cfg(feature = "std")]
289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290 write!(f, "MessengerTrustedMmrExtension",)
291 }
292
293 #[cfg(not(feature = "std"))]
294 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
295 Ok(())
296 }
297}
298
299impl<Runtime> MessengerTrustedMmrExtension<Runtime>
300where
301 Runtime: Config + scale_info::TypeInfo + fmt::Debug + Send + Sync,
302{
303 fn do_validate(
304 call: &MessengerCall<Runtime>,
305 ) -> Result<(ValidTransaction, ValidatedRelayMessage<Runtime>), TransactionValidityError> {
306 match call {
307 Call::relay_message { msg: xdm } => {
308 let consensus_state_root =
309 Runtime::MmrProofVerifier::extract_leaf_without_verifying(
310 xdm.proof.consensus_mmr_proof(),
311 )
312 .ok_or(InvalidTransaction::BadProof)?
313 .state_root();
314
315 let validated_relay_message =
316 Messenger::<Runtime>::validate_relay_message(xdm, consensus_state_root)?;
317
318 Ok((ValidTransaction::default(), validated_relay_message))
319 }
320 Call::relay_message_response { msg: xdm } => {
321 let consensus_state_root =
322 Runtime::MmrProofVerifier::extract_leaf_without_verifying(
323 xdm.proof.consensus_mmr_proof(),
324 )
325 .ok_or(InvalidTransaction::BadProof)?
326 .state_root();
327
328 let validated_relay_message =
329 Messenger::<Runtime>::validate_relay_message_response(
330 xdm,
331 consensus_state_root,
332 )?;
333
334 Ok((ValidTransaction::default(), validated_relay_message))
335 }
336 _ => Err(InvalidTransaction::Call.into()),
337 }
338 }
339}
340
341impl<Runtime> TransactionExtension<RuntimeCallFor<Runtime>>
342 for MessengerTrustedMmrExtension<Runtime>
343where
344 Runtime: Config + scale_info::TypeInfo + fmt::Debug + Send + Sync,
345 <RuntimeCallFor<Runtime> as Dispatchable>::RuntimeOrigin:
346 AsSystemOriginSigner<<Runtime as frame_system::Config>::AccountId> + From<Origin> + Clone,
347 RuntimeCallFor<Runtime>: MaybeMessengerCall<Runtime>,
348{
349 const IDENTIFIER: &'static str = "MessengerTrustedMmrExtension";
350 type Implicit = ();
351 type Val = Val<Runtime>;
352 type Pre = ();
353
354 impl_tx_ext_default!(RuntimeCallFor<Runtime>; weight);
356
357 fn validate(
358 &self,
359 origin: DispatchOriginOf<RuntimeCallFor<Runtime>>,
360 call: &RuntimeCallFor<Runtime>,
361 _info: &DispatchInfoOf<RuntimeCallFor<Runtime>>,
362 _len: usize,
363 _self_implicit: Self::Implicit,
364 _inherited_implication: &impl Implication,
365 _source: TransactionSource,
366 ) -> ValidateResult<Self::Val, RuntimeCallFor<Runtime>> {
367 if origin.as_system_origin_signer().is_some() {
369 return Ok((ValidTransaction::default(), Val::None, origin));
370 };
371
372 let messenger_call = match call.maybe_messenger_call() {
373 Some(messenger_call) => messenger_call,
374 None => return Ok((ValidTransaction::default(), Val::None, origin)),
375 };
376
377 let (validity, validated_relay_message) = Self::do_validate(messenger_call)?;
378 Ok((
379 validity,
380 Val::ValidatedRelayMessage(validated_relay_message),
381 Origin::ValidatedUnsigned.into(),
382 ))
383 }
384
385 fn prepare(
386 self,
387 val: Self::Val,
388 _origin: &DispatchOriginOf<RuntimeCallFor<Runtime>>,
389 call: &RuntimeCallFor<Runtime>,
390 _info: &DispatchInfoOf<RuntimeCallFor<Runtime>>,
391 _len: usize,
392 ) -> Result<Self::Pre, TransactionValidityError> {
393 match (call.maybe_messenger_call(), val) {
394 (Some(messenger_call), Val::ValidatedRelayMessage(validated_relay_message)) => {
396 MessengerExtension::<Runtime>::do_prepare(messenger_call, validated_relay_message)
397 }
398 (_, _) => Ok(()),
400 }
401 }
402}