referrerpolicy=no-referrer-when-downgrade

pallet_bridge_relayers/extension/
mod.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Signed extension, built around `pallet-bridge-relayers`. It is able to:
18//!
19//! - refund the cost of successful message delivery and confirmation transactions to the submitter
20//!   by registering corresponding reward in the pallet;
21//!
22//! - bump priority of messages delivery and confirmation transactions, signed by the registered
23//!   relayers.
24
25use crate::{Config as RelayersConfig, Pallet as RelayersPallet, WeightInfoExt, LOG_TARGET};
26
27use bp_messages::{ChainWithMessages, MessageNonce};
28use bp_relayers::{
29	ExplicitOrAccountParams, ExtensionCallData, ExtensionCallInfo, ExtensionConfig,
30	RewardsAccountOwner, RewardsAccountParams,
31};
32use bp_runtime::{Chain, RangeInclusiveExt, StaticStrProvider};
33use codec::{Decode, DecodeWithMemTracking, Encode};
34use core::{fmt::Debug, marker::PhantomData};
35use frame_support::{
36	dispatch::{DispatchInfo, PostDispatchInfo},
37	pallet_prelude::TransactionSource,
38	weights::Weight,
39	CloneNoBound, DebugNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound,
40};
41use frame_system::Config as SystemConfig;
42use pallet_bridge_messages::{
43	CallHelper as MessagesCallHelper, Config as BridgeMessagesConfig, LaneIdOf,
44};
45use pallet_transaction_payment::{
46	Config as TransactionPaymentConfig, OnChargeTransaction, Pallet as TransactionPaymentPallet,
47};
48use scale_info::TypeInfo;
49use sp_runtime::{
50	traits::{
51		AsSystemOriginSigner, DispatchInfoOf, Dispatchable, PostDispatchInfoOf,
52		TransactionExtension, ValidateResult, Zero,
53	},
54	transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransactionBuilder},
55	DispatchResult,
56};
57
58pub use grandpa_adapter::WithGrandpaChainExtensionConfig;
59pub use messages_adapter::WithMessagesExtensionConfig;
60pub use parachain_adapter::WithParachainExtensionConfig;
61pub use priority::*;
62
63mod grandpa_adapter;
64mod messages_adapter;
65mod parachain_adapter;
66mod priority;
67
68/// Data that is crafted in `validate`, passed to `prepare` and used at `post_dispatch` method.
69#[cfg_attr(test, derive(Debug, PartialEq))]
70pub struct PreDispatchData<
71	AccountId,
72	RemoteGrandpaChainBlockNumber: Debug,
73	LaneId: Clone + Copy + Debug,
74> {
75	/// Transaction submitter (relayer) account.
76	relayer: AccountId,
77	/// Type of the call.
78	call_info: ExtensionCallInfo<RemoteGrandpaChainBlockNumber, LaneId>,
79}
80
81impl<AccountId, RemoteGrandpaChainBlockNumber: Debug, LaneId: Clone + Copy + Debug>
82	PreDispatchData<AccountId, RemoteGrandpaChainBlockNumber, LaneId>
83{
84	/// Returns mutable reference to `finality_target` sent to the
85	/// `SubmitFinalityProof` call.
86	#[cfg(test)]
87	pub fn submit_finality_proof_info_mut(
88		&mut self,
89	) -> Option<&mut bp_header_chain::SubmitFinalityProofInfo<RemoteGrandpaChainBlockNumber>> {
90		match self.call_info {
91			ExtensionCallInfo::AllFinalityAndMsgs(ref mut info, _, _) => Some(info),
92			ExtensionCallInfo::RelayFinalityAndMsgs(ref mut info, _) => Some(info),
93			_ => None,
94		}
95	}
96}
97
98/// The actions on relayer account that need to be performed because of his actions.
99#[derive(Debug, PartialEq)]
100pub enum RelayerAccountAction<AccountId, RewardBalance, LaneId> {
101	/// Do nothing with relayer account.
102	None,
103	/// Reward the relayer.
104	Reward(AccountId, RewardsAccountParams<LaneId>, RewardBalance),
105	/// Slash the relayer.
106	Slash(AccountId, RewardsAccountParams<LaneId>),
107}
108
109/// A signed extension, built around `pallet-bridge-relayers`.
110///
111/// It may be incorporated into runtime to refund relayers for submitting correct
112/// message delivery and confirmation transactions, optionally batched with required
113/// finality proofs.
114///
115/// (Works only with `pallet-bridge-messages` and `RewardsAccountParams` as the `Reward`)
116#[derive(
117	DefaultNoBound,
118	CloneNoBound,
119	Decode,
120	DecodeWithMemTracking,
121	Encode,
122	EqNoBound,
123	PartialEqNoBound,
124	DebugNoBound,
125	TypeInfo,
126)]
127#[scale_info(skip_type_params(Runtime, Config, LaneId))]
128pub struct BridgeRelayersTransactionExtension<Runtime, Config>(PhantomData<(Runtime, Config)>);
129
130impl<R, C> BridgeRelayersTransactionExtension<R, C>
131where
132	Self: 'static + Send + Sync,
133	R: RelayersConfig<C::BridgeRelayersPalletInstance>
134		+ BridgeMessagesConfig<C::BridgeMessagesPalletInstance>
135		+ TransactionPaymentConfig,
136	C: ExtensionConfig<Runtime = R>,
137	R::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
138	<R::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<R::AccountId> + Clone,
139	<R as TransactionPaymentConfig>::OnChargeTransaction: OnChargeTransaction<R>,
140	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::Reward:
141		From<RewardsAccountParams<C::LaneId>>,
142	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::RewardBalance: From<
143		<<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance,
144	>,
145	C::LaneId: From<LaneIdOf<R, C::BridgeMessagesPalletInstance>>,
146{
147	/// Returns number of bundled messages `Some(_)`, if the given call info is a:
148	///
149	/// - message delivery transaction;
150	///
151	/// - with reasonable bundled messages that may be accepted by the messages pallet.
152	///
153	/// This function is used to check whether the transaction priority should be
154	/// virtually boosted. The relayer registration (we only boost priority for registered
155	/// relayer transactions) must be checked outside.
156	fn bundled_messages_for_priority_boost(
157		parsed_call: &ExtensionCallInfo<C::RemoteGrandpaChainBlockNumber, C::LaneId>,
158	) -> Option<MessageNonce> {
159		// we only boost priority of message delivery transactions
160		if !parsed_call.is_receive_messages_proof_call() {
161			return None;
162		}
163
164		// compute total number of messages in transaction
165		let bundled_messages = parsed_call.messages_call_info().bundled_messages().saturating_len();
166
167		// a quick check to avoid invalid high-priority transactions
168		let max_unconfirmed_messages_in_confirmation_tx = <R as BridgeMessagesConfig<C::BridgeMessagesPalletInstance>>::BridgedChain
169			::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
170		if bundled_messages > max_unconfirmed_messages_in_confirmation_tx {
171			return None;
172		}
173
174		Some(bundled_messages)
175	}
176
177	/// Given post-dispatch information, analyze the outcome of relayer call and return
178	/// actions that need to be performed on relayer account.
179	fn analyze_call_result(
180		pre: Option<PreDispatchData<R::AccountId, C::RemoteGrandpaChainBlockNumber, C::LaneId>>,
181		info: &DispatchInfo,
182		post_info: &PostDispatchInfo,
183		len: usize,
184		result: &DispatchResult,
185	) -> RelayerAccountAction<R::AccountId, R::RewardBalance, C::LaneId> {
186		// We don't refund anything for transactions that we don't support.
187		let (relayer, call_info) = match pre {
188			Some(pre) => (pre.relayer, pre.call_info),
189			_ => return RelayerAccountAction::None,
190		};
191
192		// now we know that the call is supported and we may need to reward or slash relayer
193		// => let's prepare the correspondent account that pays reward/receives slashed amount
194		let lane_id = call_info.messages_call_info().lane_id();
195		let reward_account_params = RewardsAccountParams::new(
196			lane_id,
197			<R as BridgeMessagesConfig<C::BridgeMessagesPalletInstance>>::BridgedChain::ID,
198			if call_info.is_receive_messages_proof_call() {
199				RewardsAccountOwner::ThisChain
200			} else {
201				RewardsAccountOwner::BridgedChain
202			},
203		);
204
205		// prepare return value for the case if the call has failed or it has not caused
206		// expected side effects (e.g. not all messages have been accepted)
207		//
208		// we are not checking if relayer is registered here - it happens during the slash attempt
209		//
210		// there are a couple of edge cases here:
211		//
212		// - when the relayer becomes registered during message dispatch: this is unlikely + relayer
213		//   should be ready for slashing after registration;
214		//
215		// - when relayer is registered after `validate` is called and priority is not boosted:
216		//   relayer should be ready for slashing after registration.
217		let may_slash_relayer = Self::bundled_messages_for_priority_boost(&call_info).is_some();
218		let slash_relayer_if_delivery_result = may_slash_relayer
219			.then(|| RelayerAccountAction::Slash(relayer.clone(), reward_account_params))
220			.unwrap_or(RelayerAccountAction::None);
221
222		// We don't refund anything if the transaction has failed.
223		if let Err(e) = result {
224			tracing::trace!(
225				target: LOG_TARGET,
226				error=?e,
227				id_provider=%Self::IDENTIFIER,
228				?lane_id,
229				?relayer,
230				"Relayer has submitted invalid messages transaction",
231			);
232			return slash_relayer_if_delivery_result;
233		}
234
235		// check whether the call has succeeded
236		let mut call_data = ExtensionCallData::default();
237		if !C::check_call_result(&call_info, &mut call_data, &relayer) {
238			return slash_relayer_if_delivery_result;
239		}
240
241		// regarding the tip - refund that happens here (at this side of the bridge) isn't the whole
242		// relayer compensation. He'll receive some amount at the other side of the bridge. It shall
243		// (in theory) cover the tip there. Otherwise, if we'll be compensating tip here, some
244		// malicious relayer may use huge tips, effectively depleting account that pay rewards. The
245		// cost of this attack is nothing. Hence we use zero as tip here.
246		let tip = Zero::zero();
247
248		// decrease post-dispatch weight/size using extra weight/size that we know now
249		let post_info_len = len.saturating_sub(call_data.extra_size as usize);
250		let mut post_info_weight = post_info
251			.actual_weight
252			.unwrap_or(info.total_weight())
253			.saturating_sub(call_data.extra_weight);
254
255		// let's also replace the weight of slashing relayer with the weight of rewarding relayer
256		if call_info.is_receive_messages_proof_call() {
257			post_info_weight = post_info_weight.saturating_sub(
258				<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::WeightInfo::extra_weight_of_successful_receive_messages_proof_call(),
259			);
260		}
261
262		// compute the relayer refund
263		let mut post_info = *post_info;
264		post_info.actual_weight = Some(post_info_weight);
265		let refund = Self::compute_refund(info, &post_info, post_info_len, tip);
266
267		// we can finally reward relayer
268		RelayerAccountAction::Reward(relayer, reward_account_params, refund.into())
269	}
270
271	/// Compute refund for the successful relayer transaction
272	fn compute_refund(
273		info: &DispatchInfo,
274		post_info: &PostDispatchInfo,
275		len: usize,
276		tip: <<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance,
277	) -> <<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance
278	{
279		TransactionPaymentPallet::<R>::compute_actual_fee(len as _, info, post_info, tip)
280	}
281}
282
283impl<R, C> TransactionExtension<R::RuntimeCall> for BridgeRelayersTransactionExtension<R, C>
284where
285	Self: 'static + Send + Sync,
286	R: RelayersConfig<C::BridgeRelayersPalletInstance>
287		+ BridgeMessagesConfig<C::BridgeMessagesPalletInstance>
288		+ TransactionPaymentConfig,
289	C: ExtensionConfig<Runtime = R>,
290	R::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
291	<R::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<R::AccountId> + Clone,
292	<R as TransactionPaymentConfig>::OnChargeTransaction: OnChargeTransaction<R>,
293	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::Reward:
294		From<RewardsAccountParams<C::LaneId>>,
295	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::RewardBalance: From<
296		<<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance,
297	>,
298	C::LaneId: From<LaneIdOf<R, C::BridgeMessagesPalletInstance>>,
299{
300	const IDENTIFIER: &'static str = C::IdProvider::STR;
301	type Implicit = ();
302	type Pre = Option<PreDispatchData<R::AccountId, C::RemoteGrandpaChainBlockNumber, C::LaneId>>;
303	type Val = Self::Pre;
304
305	fn weight(&self, _call: &R::RuntimeCall) -> Weight {
306		Weight::zero()
307	}
308
309	fn validate(
310		&self,
311		origin: <R::RuntimeCall as Dispatchable>::RuntimeOrigin,
312		call: &R::RuntimeCall,
313		_info: &DispatchInfoOf<R::RuntimeCall>,
314		_len: usize,
315		_self_implicit: Self::Implicit,
316		_inherited_implication: &impl Encode,
317		_source: TransactionSource,
318	) -> ValidateResult<Self::Val, R::RuntimeCall> {
319		// Prepare relevant data for `prepare`
320		let parsed_call = match C::parse_and_check_for_obsolete_call(call)? {
321			Some(parsed_call) => parsed_call,
322			None => return Ok((Default::default(), None, origin)),
323		};
324		// Those calls are only for signed transactions.
325		let relayer = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?;
326
327		let data = PreDispatchData { relayer: relayer.clone(), call_info: parsed_call };
328
329		// the following code just plays with transaction priority
330
331		// we only boost priority of presumably correct message delivery transactions
332		let bundled_messages = match Self::bundled_messages_for_priority_boost(&data.call_info) {
333			Some(bundled_messages) => bundled_messages,
334			None => return Ok((Default::default(), Some(data), origin)),
335		};
336
337		// we only boost priority if relayer has staked required balance
338		if !RelayersPallet::<R, C::BridgeRelayersPalletInstance>::is_registration_active(
339			&data.relayer,
340		) {
341			return Ok((Default::default(), Some(data), origin));
342		}
343
344		// compute priority boost
345		let priority_boost =
346			priority::compute_priority_boost::<C::PriorityBoostPerMessage>(bundled_messages);
347		let valid_transaction = ValidTransactionBuilder::default().priority(priority_boost);
348
349		tracing::trace!(
350			target: LOG_TARGET,
351			id_provider=%Self::IDENTIFIER,
352			lane_id=?data.call_info.messages_call_info().lane_id(),
353			relayer=?data.relayer,
354			%bundled_messages,
355			%priority_boost,
356			"Has boosted priority of message delivery transaction of relayer"
357		);
358
359		let validity = valid_transaction.build()?;
360		Ok((validity, Some(data), origin))
361	}
362
363	fn prepare(
364		self,
365		val: Self::Val,
366		_origin: &<R::RuntimeCall as Dispatchable>::RuntimeOrigin,
367		_call: &R::RuntimeCall,
368		_info: &DispatchInfoOf<R::RuntimeCall>,
369		_len: usize,
370	) -> Result<Self::Pre, TransactionValidityError> {
371		Ok(val.inspect(|data| {
372			tracing::trace!(
373				target: LOG_TARGET,
374				id_provider=%Self::IDENTIFIER,
375				lane_id=?data.call_info.messages_call_info().lane_id(),
376				call_info=?data.call_info,
377				"Parsed bridge transaction in prepare"
378			);
379		}))
380	}
381
382	fn post_dispatch_details(
383		pre: Self::Pre,
384		info: &DispatchInfoOf<R::RuntimeCall>,
385		post_info: &PostDispatchInfoOf<R::RuntimeCall>,
386		len: usize,
387		result: &DispatchResult,
388	) -> Result<Weight, TransactionValidityError> {
389		let lane_id = pre.as_ref().map(|p| p.call_info.messages_call_info().lane_id());
390		let call_result = Self::analyze_call_result(pre, info, post_info, len, result);
391
392		match call_result {
393			RelayerAccountAction::None => (),
394			RelayerAccountAction::Reward(relayer, reward_account, reward) => {
395				RelayersPallet::<R, C::BridgeRelayersPalletInstance>::register_relayer_reward(
396					reward_account.into(),
397					&relayer,
398					reward,
399				);
400
401				tracing::trace!(
402					target: LOG_TARGET,
403					id_provider=%Self::IDENTIFIER,
404					?lane_id,
405					?relayer,
406					?reward,
407					"Has registered reward"
408				);
409			},
410			RelayerAccountAction::Slash(relayer, slash_account) => {
411				RelayersPallet::<R, C::BridgeRelayersPalletInstance>::slash_and_deregister(
412					&relayer,
413					ExplicitOrAccountParams::Params(slash_account),
414				)
415			},
416		}
417
418		Ok(Weight::zero())
419	}
420}
421
422/// Verify that the messages pallet call, supported by extension has succeeded.
423pub(crate) fn verify_messages_call_succeeded<C>(
424	call_info: &ExtensionCallInfo<
425		C::RemoteGrandpaChainBlockNumber,
426		LaneIdOf<C::Runtime, C::BridgeMessagesPalletInstance>,
427	>,
428	_call_data: &mut ExtensionCallData,
429	relayer: &<C::Runtime as SystemConfig>::AccountId,
430) -> bool
431where
432	C: ExtensionConfig,
433	C::Runtime: BridgeMessagesConfig<C::BridgeMessagesPalletInstance>,
434{
435	let messages_call = call_info.messages_call_info();
436
437	if !MessagesCallHelper::<C::Runtime, C::BridgeMessagesPalletInstance>::was_successful(
438		messages_call,
439	) {
440		tracing::trace!(
441			target: LOG_TARGET,
442			id_provider=%C::IdProvider::STR,
443			lane_id=?call_info.messages_call_info().lane_id(),
444			?relayer,
445			"Relayer has submitted invalid messages call"
446		);
447		return false;
448	}
449
450	true
451}
452
453#[cfg(test)]
454mod tests {
455	use super::*;
456	use crate::mock::*;
457
458	use bp_header_chain::{StoredHeaderDataBuilder, SubmitFinalityProofInfo};
459	use bp_messages::{
460		source_chain::FromBridgedChainMessagesDeliveryProof,
461		target_chain::FromBridgedChainMessagesProof, BaseMessagesProofInfo, DeliveredMessages,
462		InboundLaneData, MessageNonce, MessagesCallInfo, MessagesOperatingMode, OutboundLaneData,
463		ReceiveMessagesDeliveryProofInfo, ReceiveMessagesProofInfo, UnrewardedRelayer,
464		UnrewardedRelayerOccupation, UnrewardedRelayersState,
465	};
466	use bp_parachains::{BestParaHeadHash, ParaInfo, SubmitParachainHeadsInfo};
467	use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId};
468	use bp_relayers::RuntimeWithUtilityPallet;
469	use bp_runtime::{BasicOperatingMode, HeaderId, Parachain};
470	use bp_test_utils::{make_default_justification, test_keyring, TEST_GRANDPA_SET_ID};
471	use frame_support::{
472		__private::sp_tracing,
473		assert_storage_noop, parameter_types,
474		traits::{fungible::Mutate, ReservableCurrency},
475		weights::Weight,
476	};
477	use pallet_bridge_grandpa::{Call as GrandpaCall, Pallet as GrandpaPallet, StoredAuthoritySet};
478	use pallet_bridge_messages::{Call as MessagesCall, Pallet as MessagesPallet};
479	use pallet_bridge_parachains::{Call as ParachainsCall, Pallet as ParachainsPallet};
480	use pallet_utility::Call as UtilityCall;
481	use sp_runtime::{
482		traits::{ConstU64, DispatchTransaction, Header as HeaderT},
483		transaction_validity::{
484			InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction,
485		},
486		DispatchError,
487	};
488
489	parameter_types! {
490		TestParachain: u32 = BridgedUnderlyingParachain::PARACHAIN_ID;
491		pub MsgProofsRewardsAccount: RewardsAccountParams<TestLaneIdType> = RewardsAccountParams::new(
492			test_lane_id(),
493			TEST_BRIDGED_CHAIN_ID,
494			RewardsAccountOwner::ThisChain,
495		);
496		pub MsgDeliveryProofsRewardsAccount: RewardsAccountParams<TestLaneIdType> = RewardsAccountParams::new(
497			test_lane_id(),
498			TEST_BRIDGED_CHAIN_ID,
499			RewardsAccountOwner::BridgedChain,
500		);
501	}
502
503	bp_runtime::generate_static_str_provider!(TestGrandpaExtension);
504	bp_runtime::generate_static_str_provider!(TestExtension);
505	bp_runtime::generate_static_str_provider!(TestMessagesExtension);
506
507	type TestGrandpaExtensionConfig = grandpa_adapter::WithGrandpaChainExtensionConfig<
508		StrTestGrandpaExtension,
509		TestRuntime,
510		RuntimeWithUtilityPallet<TestRuntime>,
511		(),
512		(),
513		(),
514		ConstU64<1>,
515	>;
516	type TestGrandpaExtension =
517		BridgeRelayersTransactionExtension<TestRuntime, TestGrandpaExtensionConfig>;
518	type TestExtensionConfig = parachain_adapter::WithParachainExtensionConfig<
519		StrTestExtension,
520		TestRuntime,
521		RuntimeWithUtilityPallet<TestRuntime>,
522		(),
523		(),
524		(),
525		ConstU64<1>,
526	>;
527	type TestExtension = BridgeRelayersTransactionExtension<TestRuntime, TestExtensionConfig>;
528	type TestMessagesExtensionConfig = messages_adapter::WithMessagesExtensionConfig<
529		StrTestMessagesExtension,
530		TestRuntime,
531		(),
532		(),
533		ConstU64<1>,
534	>;
535	type TestMessagesExtension =
536		BridgeRelayersTransactionExtension<TestRuntime, TestMessagesExtensionConfig>;
537
538	fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance {
539		let test_stake: ThisChainBalance = Stake::get();
540		ExistentialDeposit::get().saturating_add(test_stake * 100)
541	}
542
543	// in tests, the following accounts are equal (because of how `into_sub_account_truncating`
544	// works)
545
546	fn delivery_rewards_account() -> ThisChainAccountId {
547		TestPaymentProcedure::rewards_account(MsgProofsRewardsAccount::get())
548	}
549
550	fn confirmation_rewards_account() -> ThisChainAccountId {
551		TestPaymentProcedure::rewards_account(MsgDeliveryProofsRewardsAccount::get())
552	}
553
554	fn relayer_account_at_this_chain() -> ThisChainAccountId {
555		0
556	}
557
558	fn relayer_account_at_bridged_chain() -> BridgedChainAccountId {
559		0
560	}
561
562	fn initialize_environment(
563		best_relay_header_number: BridgedChainBlockNumber,
564		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
565		best_message: MessageNonce,
566	) {
567		let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect();
568		let best_relay_header = HeaderId(best_relay_header_number, BridgedChainHash::default());
569		pallet_bridge_grandpa::CurrentAuthoritySet::<TestRuntime>::put(
570			StoredAuthoritySet::try_new(authorities, TEST_GRANDPA_SET_ID).unwrap(),
571		);
572		pallet_bridge_grandpa::BestFinalized::<TestRuntime>::put(best_relay_header);
573		pallet_bridge_grandpa::ImportedHeaders::<TestRuntime>::insert(
574			best_relay_header.hash(),
575			bp_test_utils::test_header::<BridgedChainHeader>(0).build(),
576		);
577
578		let para_id = ParaId(TestParachain::get());
579		let para_info = ParaInfo {
580			best_head_hash: BestParaHeadHash {
581				at_relay_block_number: parachain_head_at_relay_header_number,
582				head_hash: [parachain_head_at_relay_header_number as u8; 32].into(),
583			},
584			next_imported_hash_position: 0,
585		};
586		pallet_bridge_parachains::ParasInfo::<TestRuntime>::insert(para_id, para_info);
587
588		let lane_id = test_lane_id();
589		let in_lane_data =
590			InboundLaneData { last_confirmed_nonce: best_message, ..Default::default() };
591		pallet_bridge_messages::InboundLanes::<TestRuntime>::insert(lane_id, in_lane_data);
592
593		let out_lane_data =
594			OutboundLaneData { latest_received_nonce: best_message, ..Default::default() };
595		pallet_bridge_messages::OutboundLanes::<TestRuntime>::insert(lane_id, out_lane_data);
596
597		Balances::mint_into(&delivery_rewards_account(), ExistentialDeposit::get()).unwrap();
598		Balances::mint_into(&confirmation_rewards_account(), ExistentialDeposit::get()).unwrap();
599		Balances::mint_into(
600			&relayer_account_at_this_chain(),
601			initial_balance_of_relayer_account_at_this_chain(),
602		)
603		.unwrap();
604	}
605
606	fn submit_relay_header_call(relay_header_number: BridgedChainBlockNumber) -> RuntimeCall {
607		let relay_header = BridgedChainHeader::new(
608			relay_header_number,
609			Default::default(),
610			Default::default(),
611			Default::default(),
612			Default::default(),
613		);
614		let relay_justification = make_default_justification(&relay_header);
615
616		RuntimeCall::BridgeGrandpa(GrandpaCall::submit_finality_proof {
617			finality_target: Box::new(relay_header),
618			justification: relay_justification,
619		})
620	}
621
622	fn submit_relay_header_call_ex(relay_header_number: BridgedChainBlockNumber) -> RuntimeCall {
623		let relay_header = BridgedChainHeader::new(
624			relay_header_number,
625			Default::default(),
626			Default::default(),
627			Default::default(),
628			Default::default(),
629		);
630		let relay_justification = make_default_justification(&relay_header);
631
632		RuntimeCall::BridgeGrandpa(GrandpaCall::submit_finality_proof_ex {
633			finality_target: Box::new(relay_header),
634			justification: relay_justification,
635			current_set_id: TEST_GRANDPA_SET_ID,
636			is_free_execution_expected: false,
637		})
638	}
639
640	fn submit_parachain_head_call(
641		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
642	) -> RuntimeCall {
643		RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads {
644			at_relay_block: (parachain_head_at_relay_header_number, BridgedChainHash::default()),
645			parachains: vec![(
646				ParaId(TestParachain::get()),
647				[parachain_head_at_relay_header_number as u8; 32].into(),
648			)],
649			parachain_heads_proof: ParaHeadsProof { storage_proof: Default::default() },
650		})
651	}
652
653	pub fn submit_parachain_head_call_ex(
654		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
655	) -> RuntimeCall {
656		RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads_ex {
657			at_relay_block: (parachain_head_at_relay_header_number, BridgedChainHash::default()),
658			parachains: vec![(
659				ParaId(TestParachain::get()),
660				[parachain_head_at_relay_header_number as u8; 32].into(),
661			)],
662			parachain_heads_proof: ParaHeadsProof { storage_proof: Default::default() },
663			is_free_execution_expected: false,
664		})
665	}
666
667	fn message_delivery_call(best_message: MessageNonce) -> RuntimeCall {
668		RuntimeCall::BridgeMessages(MessagesCall::receive_messages_proof {
669			relayer_id_at_bridged_chain: relayer_account_at_bridged_chain(),
670			proof: Box::new(FromBridgedChainMessagesProof {
671				bridged_header_hash: Default::default(),
672				storage_proof: Default::default(),
673				lane: test_lane_id(),
674				nonces_start: pallet_bridge_messages::InboundLanes::<TestRuntime>::get(
675					test_lane_id(),
676				)
677				.unwrap()
678				.last_delivered_nonce() +
679					1,
680				nonces_end: best_message,
681			}),
682			messages_count: 1,
683			dispatch_weight: Weight::zero(),
684		})
685	}
686
687	fn message_confirmation_call(best_message: MessageNonce) -> RuntimeCall {
688		RuntimeCall::BridgeMessages(MessagesCall::receive_messages_delivery_proof {
689			proof: FromBridgedChainMessagesDeliveryProof {
690				bridged_header_hash: Default::default(),
691				storage_proof: Default::default(),
692				lane: test_lane_id(),
693			},
694			relayers_state: UnrewardedRelayersState {
695				last_delivered_nonce: best_message,
696				..Default::default()
697			},
698		})
699	}
700
701	fn parachain_finality_and_delivery_batch_call(
702		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
703		best_message: MessageNonce,
704	) -> RuntimeCall {
705		RuntimeCall::Utility(UtilityCall::batch_all {
706			calls: vec![
707				submit_parachain_head_call(parachain_head_at_relay_header_number),
708				message_delivery_call(best_message),
709			],
710		})
711	}
712
713	fn parachain_finality_and_confirmation_batch_call(
714		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
715		best_message: MessageNonce,
716	) -> RuntimeCall {
717		RuntimeCall::Utility(UtilityCall::batch_all {
718			calls: vec![
719				submit_parachain_head_call(parachain_head_at_relay_header_number),
720				message_confirmation_call(best_message),
721			],
722		})
723	}
724
725	fn relay_finality_and_delivery_batch_call(
726		relay_header_number: BridgedChainBlockNumber,
727		best_message: MessageNonce,
728	) -> RuntimeCall {
729		RuntimeCall::Utility(UtilityCall::batch_all {
730			calls: vec![
731				submit_relay_header_call(relay_header_number),
732				message_delivery_call(best_message),
733			],
734		})
735	}
736
737	fn relay_finality_and_delivery_batch_call_ex(
738		relay_header_number: BridgedChainBlockNumber,
739		best_message: MessageNonce,
740	) -> RuntimeCall {
741		RuntimeCall::Utility(UtilityCall::batch_all {
742			calls: vec![
743				submit_relay_header_call_ex(relay_header_number),
744				message_delivery_call(best_message),
745			],
746		})
747	}
748
749	fn relay_finality_and_confirmation_batch_call(
750		relay_header_number: BridgedChainBlockNumber,
751		best_message: MessageNonce,
752	) -> RuntimeCall {
753		RuntimeCall::Utility(UtilityCall::batch_all {
754			calls: vec![
755				submit_relay_header_call(relay_header_number),
756				message_confirmation_call(best_message),
757			],
758		})
759	}
760
761	fn relay_finality_and_confirmation_batch_call_ex(
762		relay_header_number: BridgedChainBlockNumber,
763		best_message: MessageNonce,
764	) -> RuntimeCall {
765		RuntimeCall::Utility(UtilityCall::batch_all {
766			calls: vec![
767				submit_relay_header_call_ex(relay_header_number),
768				message_confirmation_call(best_message),
769			],
770		})
771	}
772
773	fn all_finality_and_delivery_batch_call(
774		relay_header_number: BridgedChainBlockNumber,
775		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
776		best_message: MessageNonce,
777	) -> RuntimeCall {
778		RuntimeCall::Utility(UtilityCall::batch_all {
779			calls: vec![
780				submit_relay_header_call(relay_header_number),
781				submit_parachain_head_call(parachain_head_at_relay_header_number),
782				message_delivery_call(best_message),
783			],
784		})
785	}
786
787	fn all_finality_and_delivery_batch_call_ex(
788		relay_header_number: BridgedChainBlockNumber,
789		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
790		best_message: MessageNonce,
791	) -> RuntimeCall {
792		RuntimeCall::Utility(UtilityCall::batch_all {
793			calls: vec![
794				submit_relay_header_call_ex(relay_header_number),
795				submit_parachain_head_call_ex(parachain_head_at_relay_header_number),
796				message_delivery_call(best_message),
797			],
798		})
799	}
800
801	fn all_finality_and_confirmation_batch_call(
802		relay_header_number: BridgedChainBlockNumber,
803		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
804		best_message: MessageNonce,
805	) -> RuntimeCall {
806		RuntimeCall::Utility(UtilityCall::batch_all {
807			calls: vec![
808				submit_relay_header_call(relay_header_number),
809				submit_parachain_head_call(parachain_head_at_relay_header_number),
810				message_confirmation_call(best_message),
811			],
812		})
813	}
814
815	fn all_finality_and_confirmation_batch_call_ex(
816		relay_header_number: BridgedChainBlockNumber,
817		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
818		best_message: MessageNonce,
819	) -> RuntimeCall {
820		RuntimeCall::Utility(UtilityCall::batch_all {
821			calls: vec![
822				submit_relay_header_call_ex(relay_header_number),
823				submit_parachain_head_call_ex(parachain_head_at_relay_header_number),
824				message_confirmation_call(best_message),
825			],
826		})
827	}
828
829	fn all_finality_pre_dispatch_data(
830	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
831		PreDispatchData {
832			relayer: relayer_account_at_this_chain(),
833			call_info: ExtensionCallInfo::AllFinalityAndMsgs(
834				SubmitFinalityProofInfo {
835					block_number: 200,
836					current_set_id: None,
837					extra_weight: Weight::zero(),
838					extra_size: 0,
839					is_mandatory: false,
840					is_free_execution_expected: false,
841				},
842				SubmitParachainHeadsInfo {
843					at_relay_block: HeaderId(200, [0u8; 32].into()),
844					para_id: ParaId(TestParachain::get()),
845					para_head_hash: [200u8; 32].into(),
846					is_free_execution_expected: false,
847				},
848				MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo {
849					base: BaseMessagesProofInfo {
850						lane_id: test_lane_id(),
851						bundled_range: 101..=200,
852						best_stored_nonce: 100,
853					},
854					unrewarded_relayers: UnrewardedRelayerOccupation {
855						free_relayer_slots:
856							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
857						free_message_slots:
858							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
859					},
860				}),
861			),
862		}
863	}
864
865	#[cfg(test)]
866	fn all_finality_pre_dispatch_data_ex(
867	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
868		let mut data = all_finality_pre_dispatch_data();
869		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
870		data
871	}
872
873	fn all_finality_confirmation_pre_dispatch_data(
874	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
875		PreDispatchData {
876			relayer: relayer_account_at_this_chain(),
877			call_info: ExtensionCallInfo::AllFinalityAndMsgs(
878				SubmitFinalityProofInfo {
879					block_number: 200,
880					current_set_id: None,
881					extra_weight: Weight::zero(),
882					extra_size: 0,
883					is_mandatory: false,
884					is_free_execution_expected: false,
885				},
886				SubmitParachainHeadsInfo {
887					at_relay_block: HeaderId(200, [0u8; 32].into()),
888					para_id: ParaId(TestParachain::get()),
889					para_head_hash: [200u8; 32].into(),
890					is_free_execution_expected: false,
891				},
892				MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
893					BaseMessagesProofInfo {
894						lane_id: test_lane_id(),
895						bundled_range: 101..=200,
896						best_stored_nonce: 100,
897					},
898				)),
899			),
900		}
901	}
902
903	fn all_finality_confirmation_pre_dispatch_data_ex(
904	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
905		let mut data = all_finality_confirmation_pre_dispatch_data();
906		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
907		data
908	}
909
910	fn relay_finality_pre_dispatch_data(
911	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
912		PreDispatchData {
913			relayer: relayer_account_at_this_chain(),
914			call_info: ExtensionCallInfo::RelayFinalityAndMsgs(
915				SubmitFinalityProofInfo {
916					block_number: 200,
917					current_set_id: None,
918					extra_weight: Weight::zero(),
919					extra_size: 0,
920					is_mandatory: false,
921					is_free_execution_expected: false,
922				},
923				MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo {
924					base: BaseMessagesProofInfo {
925						lane_id: test_lane_id(),
926						bundled_range: 101..=200,
927						best_stored_nonce: 100,
928					},
929					unrewarded_relayers: UnrewardedRelayerOccupation {
930						free_relayer_slots:
931							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
932						free_message_slots:
933							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
934					},
935				}),
936			),
937		}
938	}
939
940	fn relay_finality_pre_dispatch_data_ex(
941	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
942		let mut data = relay_finality_pre_dispatch_data();
943		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
944		data
945	}
946
947	fn relay_finality_confirmation_pre_dispatch_data(
948	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
949		PreDispatchData {
950			relayer: relayer_account_at_this_chain(),
951			call_info: ExtensionCallInfo::RelayFinalityAndMsgs(
952				SubmitFinalityProofInfo {
953					block_number: 200,
954					current_set_id: None,
955					extra_weight: Weight::zero(),
956					extra_size: 0,
957					is_mandatory: false,
958					is_free_execution_expected: false,
959				},
960				MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
961					BaseMessagesProofInfo {
962						lane_id: test_lane_id(),
963						bundled_range: 101..=200,
964						best_stored_nonce: 100,
965					},
966				)),
967			),
968		}
969	}
970
971	fn relay_finality_confirmation_pre_dispatch_data_ex(
972	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
973		let mut data = relay_finality_confirmation_pre_dispatch_data();
974		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
975		data
976	}
977
978	fn parachain_finality_pre_dispatch_data(
979	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
980		PreDispatchData {
981			relayer: relayer_account_at_this_chain(),
982			call_info: ExtensionCallInfo::ParachainFinalityAndMsgs(
983				SubmitParachainHeadsInfo {
984					at_relay_block: HeaderId(200, [0u8; 32].into()),
985					para_id: ParaId(TestParachain::get()),
986					para_head_hash: [200u8; 32].into(),
987					is_free_execution_expected: false,
988				},
989				MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo {
990					base: BaseMessagesProofInfo {
991						lane_id: test_lane_id(),
992						bundled_range: 101..=200,
993						best_stored_nonce: 100,
994					},
995					unrewarded_relayers: UnrewardedRelayerOccupation {
996						free_relayer_slots:
997							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
998						free_message_slots:
999							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
1000					},
1001				}),
1002			),
1003		}
1004	}
1005
1006	fn parachain_finality_confirmation_pre_dispatch_data(
1007	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
1008		PreDispatchData {
1009			relayer: relayer_account_at_this_chain(),
1010			call_info: ExtensionCallInfo::ParachainFinalityAndMsgs(
1011				SubmitParachainHeadsInfo {
1012					at_relay_block: HeaderId(200, [0u8; 32].into()),
1013					para_id: ParaId(TestParachain::get()),
1014					para_head_hash: [200u8; 32].into(),
1015					is_free_execution_expected: false,
1016				},
1017				MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
1018					BaseMessagesProofInfo {
1019						lane_id: test_lane_id(),
1020						bundled_range: 101..=200,
1021						best_stored_nonce: 100,
1022					},
1023				)),
1024			),
1025		}
1026	}
1027
1028	fn delivery_pre_dispatch_data<RemoteGrandpaChainBlockNumber: Debug>(
1029	) -> PreDispatchData<ThisChainAccountId, RemoteGrandpaChainBlockNumber, TestLaneIdType> {
1030		PreDispatchData {
1031			relayer: relayer_account_at_this_chain(),
1032			call_info: ExtensionCallInfo::Msgs(MessagesCallInfo::ReceiveMessagesProof(
1033				ReceiveMessagesProofInfo {
1034					base: BaseMessagesProofInfo {
1035						lane_id: test_lane_id(),
1036						bundled_range: 101..=200,
1037						best_stored_nonce: 100,
1038					},
1039					unrewarded_relayers: UnrewardedRelayerOccupation {
1040						free_relayer_slots:
1041							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
1042						free_message_slots:
1043							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
1044					},
1045				},
1046			)),
1047		}
1048	}
1049
1050	fn confirmation_pre_dispatch_data<RemoteGrandpaChainBlockNumber: Debug>(
1051	) -> PreDispatchData<ThisChainAccountId, RemoteGrandpaChainBlockNumber, TestLaneIdType> {
1052		PreDispatchData {
1053			relayer: relayer_account_at_this_chain(),
1054			call_info: ExtensionCallInfo::Msgs(MessagesCallInfo::ReceiveMessagesDeliveryProof(
1055				ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo {
1056					lane_id: test_lane_id(),
1057					bundled_range: 101..=200,
1058					best_stored_nonce: 100,
1059				}),
1060			)),
1061		}
1062	}
1063
1064	fn set_bundled_range_end(
1065		mut pre_dispatch_data: PreDispatchData<
1066			ThisChainAccountId,
1067			BridgedChainBlockNumber,
1068			TestLaneIdType,
1069		>,
1070		end: MessageNonce,
1071	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
1072		let msg_info = match pre_dispatch_data.call_info {
1073			ExtensionCallInfo::AllFinalityAndMsgs(_, _, ref mut info) => info,
1074			ExtensionCallInfo::RelayFinalityAndMsgs(_, ref mut info) => info,
1075			ExtensionCallInfo::ParachainFinalityAndMsgs(_, ref mut info) => info,
1076			ExtensionCallInfo::Msgs(ref mut info) => info,
1077		};
1078
1079		if let MessagesCallInfo::ReceiveMessagesProof(ref mut msg_info) = msg_info {
1080			msg_info.base.bundled_range = *msg_info.base.bundled_range.start()..=end
1081		}
1082
1083		pre_dispatch_data
1084	}
1085
1086	fn run_validate(call: RuntimeCall) -> TransactionValidity {
1087		let extension: TestExtension = BridgeRelayersTransactionExtension(PhantomData);
1088		extension
1089			.validate_only(
1090				Some(relayer_account_at_this_chain()).into(),
1091				&call,
1092				&DispatchInfo::default(),
1093				0,
1094				External,
1095				0,
1096			)
1097			.map(|t| t.0)
1098	}
1099
1100	fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity {
1101		let extension: TestGrandpaExtension = BridgeRelayersTransactionExtension(PhantomData);
1102		extension
1103			.validate_only(
1104				Some(relayer_account_at_this_chain()).into(),
1105				&call,
1106				&DispatchInfo::default(),
1107				0,
1108				External,
1109				0,
1110			)
1111			.map(|t| t.0)
1112	}
1113
1114	fn run_messages_validate(call: RuntimeCall) -> TransactionValidity {
1115		let extension: TestMessagesExtension = BridgeRelayersTransactionExtension(PhantomData);
1116		extension
1117			.validate_only(
1118				Some(relayer_account_at_this_chain()).into(),
1119				&call,
1120				&DispatchInfo::default(),
1121				0,
1122				External,
1123				0,
1124			)
1125			.map(|t| t.0)
1126	}
1127
1128	fn ignore_priority(tx: TransactionValidity) -> TransactionValidity {
1129		tx.map(|mut tx| {
1130			tx.priority = 0;
1131			tx
1132		})
1133	}
1134
1135	fn run_pre_dispatch(
1136		call: RuntimeCall,
1137	) -> Result<
1138		Option<PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType>>,
1139		TransactionValidityError,
1140	> {
1141		sp_tracing::try_init_simple();
1142		let extension: TestExtension = BridgeRelayersTransactionExtension(PhantomData);
1143		extension
1144			.validate_and_prepare(
1145				Some(relayer_account_at_this_chain()).into(),
1146				&call,
1147				&DispatchInfo::default(),
1148				0,
1149				0,
1150			)
1151			.map(|(pre, _)| pre)
1152	}
1153
1154	fn run_grandpa_pre_dispatch(
1155		call: RuntimeCall,
1156	) -> Result<
1157		Option<PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType>>,
1158		TransactionValidityError,
1159	> {
1160		let extension: TestGrandpaExtension = BridgeRelayersTransactionExtension(PhantomData);
1161		extension
1162			.validate_and_prepare(
1163				Some(relayer_account_at_this_chain()).into(),
1164				&call,
1165				&DispatchInfo::default(),
1166				0,
1167				0,
1168			)
1169			.map(|(pre, _)| pre)
1170	}
1171
1172	fn run_messages_pre_dispatch(
1173		call: RuntimeCall,
1174	) -> Result<
1175		Option<PreDispatchData<ThisChainAccountId, (), TestLaneIdType>>,
1176		TransactionValidityError,
1177	> {
1178		let extension: TestMessagesExtension = BridgeRelayersTransactionExtension(PhantomData);
1179		extension
1180			.validate_and_prepare(
1181				Some(relayer_account_at_this_chain()).into(),
1182				&call,
1183				&DispatchInfo::default(),
1184				0,
1185				0,
1186			)
1187			.map(|(pre, _)| pre)
1188	}
1189
1190	fn dispatch_info() -> DispatchInfo {
1191		DispatchInfo {
1192			call_weight: Weight::from_parts(
1193				frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND,
1194				0,
1195			),
1196			extension_weight: Weight::zero(),
1197			class: frame_support::dispatch::DispatchClass::Normal,
1198			pays_fee: frame_support::dispatch::Pays::Yes,
1199		}
1200	}
1201
1202	fn post_dispatch_info() -> PostDispatchInfo {
1203		PostDispatchInfo { actual_weight: None, pays_fee: frame_support::dispatch::Pays::Yes }
1204	}
1205
1206	fn run_post_dispatch(
1207		pre_dispatch_data: Option<
1208			PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType>,
1209		>,
1210		dispatch_result: DispatchResult,
1211	) {
1212		let post_dispatch_result = TestExtension::post_dispatch_details(
1213			pre_dispatch_data,
1214			&dispatch_info(),
1215			&post_dispatch_info(),
1216			1024,
1217			&dispatch_result,
1218		);
1219		assert_eq!(post_dispatch_result, Ok(Weight::zero()));
1220	}
1221
1222	fn expected_delivery_reward() -> RewardBalance {
1223		let mut post_dispatch_info = post_dispatch_info();
1224		let extra_weight = <TestRuntime as RelayersConfig>::WeightInfo::extra_weight_of_successful_receive_messages_proof_call();
1225		post_dispatch_info.actual_weight =
1226			Some(dispatch_info().call_weight.saturating_sub(extra_weight));
1227		pallet_transaction_payment::Pallet::<TestRuntime>::compute_actual_fee(
1228			1024,
1229			&dispatch_info(),
1230			&post_dispatch_info,
1231			Zero::zero(),
1232		)
1233	}
1234
1235	fn expected_confirmation_reward() -> RewardBalance {
1236		pallet_transaction_payment::Pallet::<TestRuntime>::compute_actual_fee(
1237			1024,
1238			&dispatch_info(),
1239			&post_dispatch_info(),
1240			Zero::zero(),
1241		)
1242	}
1243
1244	#[test]
1245	fn validate_doesnt_boost_transaction_priority_if_relayer_is_not_registered() {
1246		run_test(|| {
1247			initialize_environment(100, 100, 100);
1248			Balances::set_balance(&relayer_account_at_this_chain(), ExistentialDeposit::get());
1249
1250			// message delivery is failing
1251			assert_eq!(run_validate(message_delivery_call(200)), Ok(Default::default()),);
1252			assert_eq!(
1253				run_validate(parachain_finality_and_delivery_batch_call(200, 200)),
1254				Ok(Default::default()),
1255			);
1256			assert_eq!(
1257				run_validate(all_finality_and_delivery_batch_call(200, 200, 200)),
1258				Ok(Default::default()),
1259			);
1260			// message confirmation validation is passing
1261			assert_eq!(
1262				ignore_priority(run_validate(message_confirmation_call(200))),
1263				Ok(Default::default()),
1264			);
1265			assert_eq!(
1266				ignore_priority(run_validate(parachain_finality_and_confirmation_batch_call(
1267					200, 200
1268				))),
1269				Ok(Default::default()),
1270			);
1271			assert_eq!(
1272				ignore_priority(run_validate(all_finality_and_confirmation_batch_call(
1273					200, 200, 200
1274				))),
1275				Ok(Default::default()),
1276			);
1277		});
1278	}
1279
1280	#[test]
1281	fn validate_boosts_priority_of_message_delivery_transactions() {
1282		run_test(|| {
1283			initialize_environment(100, 100, 100);
1284
1285			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1286				.unwrap();
1287
1288			let priority_of_100_messages_delivery =
1289				run_validate(message_delivery_call(200)).unwrap().priority;
1290			let priority_of_200_messages_delivery =
1291				run_validate(message_delivery_call(300)).unwrap().priority;
1292			assert!(
1293				priority_of_200_messages_delivery > priority_of_100_messages_delivery,
1294				"Invalid priorities: {} for 200 messages vs {} for 100 messages",
1295				priority_of_200_messages_delivery,
1296				priority_of_100_messages_delivery,
1297			);
1298
1299			let priority_of_100_messages_confirmation =
1300				run_validate(message_confirmation_call(200)).unwrap().priority;
1301			let priority_of_200_messages_confirmation =
1302				run_validate(message_confirmation_call(300)).unwrap().priority;
1303			assert_eq!(
1304				priority_of_100_messages_confirmation,
1305				priority_of_200_messages_confirmation
1306			);
1307		});
1308	}
1309
1310	#[test]
1311	fn validate_does_not_boost_priority_of_message_delivery_transactions_with_too_many_messages() {
1312		run_test(|| {
1313			initialize_environment(100, 100, 100);
1314
1315			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1316				.unwrap();
1317
1318			let priority_of_max_messages_delivery = run_validate(message_delivery_call(
1319				100 + BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
1320			))
1321			.unwrap()
1322			.priority;
1323			let priority_of_more_than_max_messages_delivery = run_validate(message_delivery_call(
1324				100 + BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX + 1,
1325			))
1326			.unwrap()
1327			.priority;
1328
1329			assert!(
1330				priority_of_max_messages_delivery > priority_of_more_than_max_messages_delivery,
1331				"Invalid priorities: {} for MAX messages vs {} for MAX+1 messages",
1332				priority_of_max_messages_delivery,
1333				priority_of_more_than_max_messages_delivery,
1334			);
1335		});
1336	}
1337
1338	#[test]
1339	fn validate_allows_non_obsolete_transactions() {
1340		run_test(|| {
1341			initialize_environment(100, 100, 100);
1342
1343			assert_eq!(
1344				ignore_priority(run_validate(message_delivery_call(200))),
1345				Ok(ValidTransaction::default()),
1346			);
1347			assert_eq!(
1348				ignore_priority(run_validate(message_confirmation_call(200))),
1349				Ok(ValidTransaction::default()),
1350			);
1351			assert_eq!(
1352				ignore_priority(run_messages_validate(message_delivery_call(200))),
1353				Ok(ValidTransaction::default()),
1354			);
1355
1356			assert_eq!(
1357				ignore_priority(run_validate(parachain_finality_and_delivery_batch_call(200, 200))),
1358				Ok(ValidTransaction::default()),
1359			);
1360			assert_eq!(
1361				ignore_priority(run_validate(parachain_finality_and_confirmation_batch_call(
1362					200, 200
1363				))),
1364				Ok(ValidTransaction::default()),
1365			);
1366
1367			assert_eq!(
1368				ignore_priority(run_validate(all_finality_and_delivery_batch_call(200, 200, 200))),
1369				Ok(ValidTransaction::default()),
1370			);
1371			assert_eq!(
1372				ignore_priority(run_validate(all_finality_and_confirmation_batch_call(
1373					200, 200, 200
1374				))),
1375				Ok(ValidTransaction::default()),
1376			);
1377		});
1378	}
1379
1380	#[test]
1381	fn ext_rejects_batch_with_obsolete_relay_chain_header() {
1382		run_test(|| {
1383			initialize_environment(100, 100, 100);
1384
1385			assert_eq!(
1386				run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)),
1387				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1388			);
1389			assert_eq!(
1390				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(100, 200, 200)),
1391				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1392			);
1393
1394			assert_eq!(
1395				run_validate(all_finality_and_delivery_batch_call(100, 200, 200)),
1396				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1397			);
1398			assert_eq!(
1399				run_validate(all_finality_and_delivery_batch_call_ex(100, 200, 200)),
1400				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1401			);
1402		});
1403	}
1404
1405	#[test]
1406	fn ext_rejects_batch_with_obsolete_parachain_head() {
1407		run_test(|| {
1408			initialize_environment(100, 100, 100);
1409
1410			assert_eq!(
1411				run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)),
1412				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1413			);
1414			assert_eq!(
1415				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(101, 100, 200)),
1416				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1417			);
1418			assert_eq!(
1419				run_validate(all_finality_and_delivery_batch_call(101, 100, 200)),
1420				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1421			);
1422			assert_eq!(
1423				run_validate(all_finality_and_delivery_batch_call_ex(101, 100, 200)),
1424				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1425			);
1426
1427			assert_eq!(
1428				run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)),
1429				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1430			);
1431			assert_eq!(
1432				run_validate(parachain_finality_and_delivery_batch_call(100, 200)),
1433				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1434			);
1435		});
1436	}
1437
1438	#[test]
1439	fn ext_rejects_batch_with_obsolete_messages() {
1440		run_test(|| {
1441			initialize_environment(100, 100, 100);
1442
1443			assert_eq!(
1444				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)),
1445				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1446			);
1447			assert_eq!(
1448				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 100)),
1449				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1450			);
1451			assert_eq!(
1452				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 100)),
1453				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1454			);
1455			assert_eq!(
1456				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 100)),
1457				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1458			);
1459
1460			assert_eq!(
1461				run_validate(all_finality_and_delivery_batch_call(200, 200, 100)),
1462				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1463			);
1464			assert_eq!(
1465				run_validate(all_finality_and_delivery_batch_call_ex(200, 200, 100)),
1466				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1467			);
1468			assert_eq!(
1469				run_validate(all_finality_and_confirmation_batch_call(200, 200, 100)),
1470				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1471			);
1472			assert_eq!(
1473				run_validate(all_finality_and_confirmation_batch_call_ex(200, 200, 100)),
1474				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1475			);
1476
1477			assert_eq!(
1478				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)),
1479				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1480			);
1481			assert_eq!(
1482				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 100)),
1483				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1484			);
1485
1486			assert_eq!(
1487				run_validate(parachain_finality_and_delivery_batch_call(200, 100)),
1488				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1489			);
1490			assert_eq!(
1491				run_validate(parachain_finality_and_confirmation_batch_call(200, 100)),
1492				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1493			);
1494		});
1495	}
1496
1497	#[test]
1498	fn ext_rejects_batch_with_grandpa_finality_proof_when_grandpa_pallet_is_halted() {
1499		run_test(|| {
1500			initialize_environment(100, 100, 100);
1501
1502			GrandpaPallet::<TestRuntime, ()>::set_operating_mode(
1503				RuntimeOrigin::root(),
1504				BasicOperatingMode::Halted,
1505			)
1506			.unwrap();
1507
1508			assert_eq!(
1509				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1510				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1511			);
1512			assert_eq!(
1513				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1514				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1515			);
1516			assert_eq!(
1517				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1518				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1519			);
1520			assert_eq!(
1521				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1522				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1523			);
1524		});
1525	}
1526
1527	#[test]
1528	fn ext_rejects_batch_with_parachain_finality_proof_when_parachains_pallet_is_halted() {
1529		run_test(|| {
1530			initialize_environment(100, 100, 100);
1531
1532			ParachainsPallet::<TestRuntime, ()>::set_operating_mode(
1533				RuntimeOrigin::root(),
1534				BasicOperatingMode::Halted,
1535			)
1536			.unwrap();
1537
1538			assert_eq!(
1539				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1540				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1541			);
1542			assert_eq!(
1543				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1544				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1545			);
1546			assert_eq!(
1547				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1548				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1549			);
1550			assert_eq!(
1551				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1552				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1553			);
1554
1555			assert_eq!(
1556				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)),
1557				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1558			);
1559			assert_eq!(
1560				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)),
1561				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1562			);
1563		});
1564	}
1565
1566	#[test]
1567	fn ext_rejects_transaction_when_messages_pallet_is_halted() {
1568		run_test(|| {
1569			initialize_environment(100, 100, 100);
1570
1571			MessagesPallet::<TestRuntime, ()>::set_operating_mode(
1572				RuntimeOrigin::root(),
1573				MessagesOperatingMode::Basic(BasicOperatingMode::Halted),
1574			)
1575			.unwrap();
1576
1577			assert_eq!(
1578				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1579				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1580			);
1581			assert_eq!(
1582				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1583				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1584			);
1585			assert_eq!(
1586				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1587				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1588			);
1589			assert_eq!(
1590				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1591				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1592			);
1593
1594			assert_eq!(
1595				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)),
1596				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1597			);
1598			assert_eq!(
1599				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)),
1600				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1601			);
1602
1603			assert_eq!(
1604				run_pre_dispatch(message_delivery_call(200)),
1605				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1606			);
1607			assert_eq!(
1608				run_pre_dispatch(message_confirmation_call(200)),
1609				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1610			);
1611		});
1612	}
1613
1614	#[test]
1615	fn pre_dispatch_parses_batch_with_relay_chain_and_parachain_headers() {
1616		run_test(|| {
1617			initialize_environment(100, 100, 100);
1618
1619			assert_eq!(
1620				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1621				Ok(Some(all_finality_pre_dispatch_data())),
1622			);
1623			assert_eq!(
1624				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1625				Ok(Some(all_finality_pre_dispatch_data_ex())),
1626			);
1627			assert_eq!(
1628				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1629				Ok(Some(all_finality_confirmation_pre_dispatch_data())),
1630			);
1631			assert_eq!(
1632				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1633				Ok(Some(all_finality_confirmation_pre_dispatch_data_ex())),
1634			);
1635		});
1636	}
1637
1638	#[test]
1639	fn pre_dispatch_parses_batch_with_parachain_header() {
1640		run_test(|| {
1641			initialize_environment(100, 100, 100);
1642
1643			assert_eq!(
1644				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)),
1645				Ok(Some(parachain_finality_pre_dispatch_data())),
1646			);
1647			assert_eq!(
1648				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)),
1649				Ok(Some(parachain_finality_confirmation_pre_dispatch_data())),
1650			);
1651		});
1652	}
1653
1654	#[test]
1655	fn pre_dispatch_fails_to_parse_batch_with_multiple_parachain_headers() {
1656		run_test(|| {
1657			initialize_environment(100, 100, 100);
1658
1659			let call = RuntimeCall::Utility(UtilityCall::batch_all {
1660				calls: vec![
1661					RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads {
1662						at_relay_block: (100, BridgedChainHash::default()),
1663						parachains: vec![
1664							(ParaId(TestParachain::get()), [1u8; 32].into()),
1665							(ParaId(TestParachain::get() + 1), [1u8; 32].into()),
1666						],
1667						parachain_heads_proof: ParaHeadsProof { storage_proof: Default::default() },
1668					}),
1669					message_delivery_call(200),
1670				],
1671			});
1672
1673			assert_eq!(run_pre_dispatch(call), Ok(None),);
1674		});
1675	}
1676
1677	#[test]
1678	fn pre_dispatch_parses_message_transaction() {
1679		run_test(|| {
1680			initialize_environment(100, 100, 100);
1681
1682			assert_eq!(
1683				run_pre_dispatch(message_delivery_call(200)),
1684				Ok(Some(delivery_pre_dispatch_data())),
1685			);
1686			assert_eq!(
1687				run_pre_dispatch(message_confirmation_call(200)),
1688				Ok(Some(confirmation_pre_dispatch_data())),
1689			);
1690		});
1691	}
1692
1693	#[test]
1694	fn post_dispatch_ignores_unknown_transaction() {
1695		run_test(|| {
1696			assert_storage_noop!(run_post_dispatch(None, Ok(())));
1697		});
1698	}
1699
1700	#[test]
1701	fn post_dispatch_ignores_failed_transaction() {
1702		run_test(|| {
1703			assert_storage_noop!(run_post_dispatch(
1704				Some(all_finality_pre_dispatch_data()),
1705				Err(DispatchError::BadOrigin)
1706			));
1707		});
1708	}
1709
1710	#[test]
1711	fn post_dispatch_ignores_transaction_that_has_not_updated_relay_chain_state() {
1712		run_test(|| {
1713			initialize_environment(100, 200, 200);
1714
1715			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1716		});
1717	}
1718
1719	#[test]
1720	fn post_dispatch_ignores_transaction_that_has_not_updated_parachain_state() {
1721		run_test(|| {
1722			initialize_environment(200, 100, 200);
1723
1724			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1725			assert_storage_noop!(run_post_dispatch(
1726				Some(parachain_finality_pre_dispatch_data()),
1727				Ok(())
1728			));
1729		});
1730	}
1731
1732	#[test]
1733	fn post_dispatch_ignores_transaction_that_has_not_delivered_any_messages() {
1734		run_test(|| {
1735			initialize_environment(200, 200, 100);
1736
1737			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1738			assert_storage_noop!(run_post_dispatch(
1739				Some(parachain_finality_pre_dispatch_data()),
1740				Ok(())
1741			));
1742			assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())));
1743
1744			assert_storage_noop!(run_post_dispatch(
1745				Some(all_finality_confirmation_pre_dispatch_data()),
1746				Ok(())
1747			));
1748			assert_storage_noop!(run_post_dispatch(
1749				Some(parachain_finality_confirmation_pre_dispatch_data()),
1750				Ok(())
1751			));
1752			assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())));
1753		});
1754	}
1755
1756	#[test]
1757	fn post_dispatch_ignores_transaction_that_has_not_delivered_all_messages() {
1758		run_test(|| {
1759			initialize_environment(200, 200, 150);
1760
1761			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1762			assert_storage_noop!(run_post_dispatch(
1763				Some(parachain_finality_pre_dispatch_data()),
1764				Ok(())
1765			));
1766			assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())));
1767
1768			assert_storage_noop!(run_post_dispatch(
1769				Some(all_finality_confirmation_pre_dispatch_data()),
1770				Ok(())
1771			));
1772			assert_storage_noop!(run_post_dispatch(
1773				Some(parachain_finality_confirmation_pre_dispatch_data()),
1774				Ok(())
1775			));
1776			assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())));
1777		});
1778	}
1779
1780	#[test]
1781	fn post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight() {
1782		run_test(|| {
1783			initialize_environment(200, 200, 200);
1784
1785			let mut _dispatch_info = dispatch_info();
1786			_dispatch_info.call_weight = Weight::from_parts(
1787				frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2,
1788				0,
1789			);
1790
1791			// without any size/weight refund: we expect regular reward
1792			let pre_dispatch_data = all_finality_pre_dispatch_data();
1793			let regular_reward = expected_delivery_reward();
1794			run_post_dispatch(Some(pre_dispatch_data), Ok(()));
1795			assert_eq!(
1796				RelayersPallet::<TestRuntime>::relayer_reward(
1797					relayer_account_at_this_chain(),
1798					MsgProofsRewardsAccount::get()
1799				),
1800				Some(regular_reward),
1801			);
1802
1803			// now repeat the same with size+weight refund: we expect smaller reward
1804			let mut pre_dispatch_data = all_finality_pre_dispatch_data();
1805			match pre_dispatch_data.call_info {
1806				ExtensionCallInfo::AllFinalityAndMsgs(ref mut info, ..) => {
1807					info.extra_weight.set_ref_time(
1808						frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND,
1809					);
1810					info.extra_size = 32;
1811				},
1812				_ => unreachable!(),
1813			}
1814			run_post_dispatch(Some(pre_dispatch_data), Ok(()));
1815			let reward_after_two_calls = RelayersPallet::<TestRuntime>::relayer_reward(
1816				relayer_account_at_this_chain(),
1817				MsgProofsRewardsAccount::get(),
1818			)
1819			.unwrap();
1820			assert!(
1821				reward_after_two_calls < 2 * regular_reward,
1822				"{}  must be < 2 * {}",
1823				reward_after_two_calls,
1824				2 * regular_reward,
1825			);
1826		});
1827	}
1828
1829	#[test]
1830	fn post_dispatch_refunds_relayer_in_all_finality_batch() {
1831		run_test(|| {
1832			initialize_environment(200, 200, 200);
1833
1834			run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()));
1835			assert_eq!(
1836				RelayersPallet::<TestRuntime>::relayer_reward(
1837					relayer_account_at_this_chain(),
1838					MsgProofsRewardsAccount::get()
1839				),
1840				Some(expected_delivery_reward()),
1841			);
1842
1843			run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(()));
1844			assert_eq!(
1845				RelayersPallet::<TestRuntime>::relayer_reward(
1846					relayer_account_at_this_chain(),
1847					MsgDeliveryProofsRewardsAccount::get()
1848				),
1849				Some(expected_confirmation_reward()),
1850			);
1851		});
1852	}
1853
1854	#[test]
1855	fn post_dispatch_refunds_relayer_in_parachain_finality_batch() {
1856		run_test(|| {
1857			initialize_environment(200, 200, 200);
1858
1859			run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(()));
1860			assert_eq!(
1861				RelayersPallet::<TestRuntime>::relayer_reward(
1862					relayer_account_at_this_chain(),
1863					MsgProofsRewardsAccount::get()
1864				),
1865				Some(expected_delivery_reward()),
1866			);
1867
1868			run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(()));
1869			assert_eq!(
1870				RelayersPallet::<TestRuntime>::relayer_reward(
1871					relayer_account_at_this_chain(),
1872					MsgDeliveryProofsRewardsAccount::get()
1873				),
1874				Some(expected_confirmation_reward()),
1875			);
1876		});
1877	}
1878
1879	#[test]
1880	fn post_dispatch_refunds_relayer_in_message_transaction() {
1881		run_test(|| {
1882			initialize_environment(200, 200, 200);
1883
1884			run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()));
1885			assert_eq!(
1886				RelayersPallet::<TestRuntime>::relayer_reward(
1887					relayer_account_at_this_chain(),
1888					MsgProofsRewardsAccount::get()
1889				),
1890				Some(expected_delivery_reward()),
1891			);
1892
1893			run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()));
1894			assert_eq!(
1895				RelayersPallet::<TestRuntime>::relayer_reward(
1896					relayer_account_at_this_chain(),
1897					MsgDeliveryProofsRewardsAccount::get()
1898				),
1899				Some(expected_confirmation_reward()),
1900			);
1901		});
1902	}
1903
1904	#[test]
1905	fn post_dispatch_slashing_relayer_stake() {
1906		run_test(|| {
1907			initialize_environment(200, 200, 100);
1908
1909			let delivery_rewards_account_balance =
1910				Balances::free_balance(delivery_rewards_account());
1911
1912			let test_stake: ThisChainBalance = Stake::get();
1913			Balances::set_balance(
1914				&relayer_account_at_this_chain(),
1915				ExistentialDeposit::get() + test_stake * 10,
1916			);
1917
1918			// slashing works for message delivery calls
1919			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1920				.unwrap();
1921			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1922			run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()));
1923			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0);
1924			assert_eq!(
1925				delivery_rewards_account_balance + test_stake,
1926				Balances::free_balance(delivery_rewards_account())
1927			);
1928
1929			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1930				.unwrap();
1931			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1932			run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(()));
1933			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0);
1934			assert_eq!(
1935				delivery_rewards_account_balance + test_stake * 2,
1936				Balances::free_balance(delivery_rewards_account())
1937			);
1938
1939			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1940				.unwrap();
1941			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1942			run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()));
1943			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0);
1944			assert_eq!(
1945				delivery_rewards_account_balance + test_stake * 3,
1946				Balances::free_balance(delivery_rewards_account())
1947			);
1948
1949			// reserve doesn't work for message confirmation calls
1950			let confirmation_rewards_account_balance =
1951				Balances::free_balance(confirmation_rewards_account());
1952
1953			Balances::reserve(&relayer_account_at_this_chain(), test_stake).unwrap();
1954			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1955
1956			assert_eq!(
1957				confirmation_rewards_account_balance,
1958				Balances::free_balance(confirmation_rewards_account())
1959			);
1960			run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()));
1961			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1962
1963			run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(()));
1964			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1965
1966			run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(()));
1967			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1968
1969			// check that unreserve has happened, not slashing
1970			assert_eq!(
1971				delivery_rewards_account_balance + test_stake * 3,
1972				Balances::free_balance(delivery_rewards_account())
1973			);
1974			assert_eq!(
1975				confirmation_rewards_account_balance,
1976				Balances::free_balance(confirmation_rewards_account())
1977			);
1978		});
1979	}
1980
1981	fn run_analyze_call_result(
1982		pre_dispatch_data: PreDispatchData<
1983			ThisChainAccountId,
1984			BridgedChainBlockNumber,
1985			TestLaneIdType,
1986		>,
1987		dispatch_result: DispatchResult,
1988	) -> RelayerAccountAction<ThisChainAccountId, RewardBalance, TestLaneIdType> {
1989		TestExtension::analyze_call_result(
1990			Some(pre_dispatch_data),
1991			&dispatch_info(),
1992			&post_dispatch_info(),
1993			1024,
1994			&dispatch_result,
1995		)
1996	}
1997
1998	#[test]
1999	fn analyze_call_result_shall_not_slash_for_transactions_with_too_many_messages() {
2000		run_test(|| {
2001			initialize_environment(100, 100, 100);
2002
2003			// the `analyze_call_result` should return slash if number of bundled messages is
2004			// within reasonable limits
2005			assert_eq!(
2006				run_analyze_call_result(all_finality_pre_dispatch_data(), Ok(())),
2007				RelayerAccountAction::Slash(
2008					relayer_account_at_this_chain(),
2009					MsgProofsRewardsAccount::get()
2010				),
2011			);
2012			assert_eq!(
2013				run_analyze_call_result(parachain_finality_pre_dispatch_data(), Ok(())),
2014				RelayerAccountAction::Slash(
2015					relayer_account_at_this_chain(),
2016					MsgProofsRewardsAccount::get()
2017				),
2018			);
2019			assert_eq!(
2020				run_analyze_call_result(delivery_pre_dispatch_data(), Ok(())),
2021				RelayerAccountAction::Slash(
2022					relayer_account_at_this_chain(),
2023					MsgProofsRewardsAccount::get()
2024				),
2025			);
2026
2027			// the `analyze_call_result` should not return slash if number of bundled messages is
2028			// larger than the
2029			assert_eq!(
2030				run_analyze_call_result(
2031					set_bundled_range_end(all_finality_pre_dispatch_data(), 1_000_000),
2032					Ok(())
2033				),
2034				RelayerAccountAction::None,
2035			);
2036			assert_eq!(
2037				run_analyze_call_result(
2038					set_bundled_range_end(parachain_finality_pre_dispatch_data(), 1_000_000),
2039					Ok(())
2040				),
2041				RelayerAccountAction::None,
2042			);
2043			assert_eq!(
2044				run_analyze_call_result(
2045					set_bundled_range_end(delivery_pre_dispatch_data(), 1_000_000),
2046					Ok(())
2047				),
2048				RelayerAccountAction::None,
2049			);
2050		});
2051	}
2052
2053	#[test]
2054	fn grandpa_ext_only_parses_valid_batches() {
2055		run_test(|| {
2056			initialize_environment(100, 100, 100);
2057
2058			// relay + parachain + message delivery calls batch is ignored
2059			assert_eq!(
2060				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2061					&all_finality_and_delivery_batch_call(200, 200, 200)
2062				),
2063				Ok(None),
2064			);
2065
2066			// relay + parachain + message confirmation calls batch is ignored
2067			assert_eq!(
2068				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2069					&all_finality_and_confirmation_batch_call(200, 200, 200)
2070				),
2071				Ok(None),
2072			);
2073
2074			// parachain + message delivery call batch is ignored
2075			assert_eq!(
2076				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2077					&parachain_finality_and_delivery_batch_call(200, 200)
2078				),
2079				Ok(None),
2080			);
2081
2082			// parachain + message confirmation call batch is ignored
2083			assert_eq!(
2084				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2085					&parachain_finality_and_confirmation_batch_call(200, 200)
2086				),
2087				Ok(None),
2088			);
2089
2090			// relay + message delivery call batch is accepted
2091			assert_eq!(
2092				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2093					&relay_finality_and_delivery_batch_call(200, 200)
2094				),
2095				Ok(Some(relay_finality_pre_dispatch_data().call_info)),
2096			);
2097
2098			// relay + message confirmation call batch is accepted
2099			assert_eq!(
2100				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2101					&relay_finality_and_confirmation_batch_call(200, 200)
2102				),
2103				Ok(Some(relay_finality_confirmation_pre_dispatch_data().call_info)),
2104			);
2105
2106			// message delivery call batch is accepted
2107			assert_eq!(
2108				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2109					&message_delivery_call(200)
2110				),
2111				Ok(Some(delivery_pre_dispatch_data().call_info)),
2112			);
2113
2114			// message confirmation call batch is accepted
2115			assert_eq!(
2116				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2117					&message_confirmation_call(200)
2118				),
2119				Ok(Some(confirmation_pre_dispatch_data().call_info)),
2120			);
2121		});
2122	}
2123
2124	#[test]
2125	fn messages_ext_only_parses_standalone_transactions() {
2126		run_test(|| {
2127			initialize_environment(100, 100, 100);
2128
2129			// relay + parachain + message delivery calls batch is ignored
2130			assert_eq!(
2131				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2132					&all_finality_and_delivery_batch_call(200, 200, 200)
2133				),
2134				Ok(None),
2135			);
2136			assert_eq!(
2137				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2138					&all_finality_and_delivery_batch_call_ex(200, 200, 200)
2139				),
2140				Ok(None),
2141			);
2142
2143			// relay + parachain + message confirmation calls batch is ignored
2144			assert_eq!(
2145				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2146					&all_finality_and_confirmation_batch_call(200, 200, 200)
2147				),
2148				Ok(None),
2149			);
2150			assert_eq!(
2151				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2152					&all_finality_and_confirmation_batch_call_ex(200, 200, 200)
2153				),
2154				Ok(None),
2155			);
2156
2157			// parachain + message delivery call batch is ignored
2158			assert_eq!(
2159				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2160					&parachain_finality_and_delivery_batch_call(200, 200)
2161				),
2162				Ok(None),
2163			);
2164
2165			// parachain + message confirmation call batch is ignored
2166			assert_eq!(
2167				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2168					&parachain_finality_and_confirmation_batch_call(200, 200)
2169				),
2170				Ok(None),
2171			);
2172
2173			// relay + message delivery call batch is ignored
2174			assert_eq!(
2175				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2176					&relay_finality_and_delivery_batch_call(200, 200)
2177				),
2178				Ok(None),
2179			);
2180			assert_eq!(
2181				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2182					&relay_finality_and_delivery_batch_call_ex(200, 200)
2183				),
2184				Ok(None),
2185			);
2186
2187			// relay + message confirmation call batch is ignored
2188			assert_eq!(
2189				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2190					&relay_finality_and_confirmation_batch_call(200, 200)
2191				),
2192				Ok(None),
2193			);
2194			assert_eq!(
2195				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2196					&relay_finality_and_confirmation_batch_call_ex(200, 200)
2197				),
2198				Ok(None),
2199			);
2200
2201			// message delivery call batch is accepted
2202			assert_eq!(
2203				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2204					&message_delivery_call(200)
2205				),
2206				Ok(Some(delivery_pre_dispatch_data().call_info)),
2207			);
2208
2209			// message confirmation call batch is accepted
2210			assert_eq!(
2211				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2212					&message_confirmation_call(200)
2213				),
2214				Ok(Some(confirmation_pre_dispatch_data().call_info)),
2215			);
2216		});
2217	}
2218
2219	#[test]
2220	fn messages_ext_rejects_calls_with_obsolete_messages() {
2221		run_test(|| {
2222			initialize_environment(100, 100, 100);
2223
2224			assert_eq!(
2225				run_messages_pre_dispatch(message_delivery_call(100)),
2226				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2227			);
2228			assert_eq!(
2229				run_messages_pre_dispatch(message_confirmation_call(100)),
2230				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2231			);
2232
2233			assert_eq!(
2234				run_messages_validate(message_delivery_call(100)),
2235				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2236			);
2237			assert_eq!(
2238				run_messages_validate(message_confirmation_call(100)),
2239				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2240			);
2241		});
2242	}
2243
2244	#[test]
2245	fn messages_ext_accepts_calls_with_new_messages() {
2246		run_test(|| {
2247			initialize_environment(100, 100, 100);
2248
2249			assert_eq!(
2250				run_messages_pre_dispatch(message_delivery_call(200)),
2251				Ok(Some(delivery_pre_dispatch_data())),
2252			);
2253			assert_eq!(
2254				run_messages_pre_dispatch(message_confirmation_call(200)),
2255				Ok(Some(confirmation_pre_dispatch_data())),
2256			);
2257
2258			assert_eq!(run_messages_validate(message_delivery_call(200)), Ok(Default::default()),);
2259			assert_eq!(
2260				run_messages_validate(message_confirmation_call(200)),
2261				Ok(Default::default()),
2262			);
2263		});
2264	}
2265
2266	#[test]
2267	fn grandpa_ext_rejects_batch_with_obsolete_relay_chain_header() {
2268		run_test(|| {
2269			initialize_environment(100, 100, 100);
2270
2271			assert_eq!(
2272				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(100, 200)),
2273				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2274			);
2275			assert_eq!(
2276				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(100, 200)),
2277				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2278			);
2279
2280			assert_eq!(
2281				run_grandpa_validate(relay_finality_and_delivery_batch_call(100, 200)),
2282				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2283			);
2284			assert_eq!(
2285				run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(100, 200)),
2286				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2287			);
2288		});
2289	}
2290
2291	#[test]
2292	fn grandpa_ext_rejects_calls_with_obsolete_messages() {
2293		run_test(|| {
2294			initialize_environment(100, 100, 100);
2295
2296			assert_eq!(
2297				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 100)),
2298				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2299			);
2300			assert_eq!(
2301				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(200, 100)),
2302				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2303			);
2304			assert_eq!(
2305				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 100)),
2306				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2307			);
2308			assert_eq!(
2309				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call_ex(200, 100)),
2310				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2311			);
2312
2313			assert_eq!(
2314				run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 100)),
2315				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2316			);
2317			assert_eq!(
2318				run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(200, 100)),
2319				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2320			);
2321			assert_eq!(
2322				run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 100)),
2323				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2324			);
2325			assert_eq!(
2326				run_grandpa_validate(relay_finality_and_confirmation_batch_call_ex(200, 100)),
2327				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2328			);
2329
2330			assert_eq!(
2331				run_grandpa_pre_dispatch(message_delivery_call(100)),
2332				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2333			);
2334			assert_eq!(
2335				run_grandpa_pre_dispatch(message_confirmation_call(100)),
2336				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2337			);
2338
2339			assert_eq!(
2340				run_grandpa_validate(message_delivery_call(100)),
2341				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2342			);
2343			assert_eq!(
2344				run_grandpa_validate(message_confirmation_call(100)),
2345				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2346			);
2347		});
2348	}
2349
2350	#[test]
2351	fn grandpa_ext_accepts_calls_with_new_messages() {
2352		run_test(|| {
2353			initialize_environment(100, 100, 100);
2354
2355			assert_eq!(
2356				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 200)),
2357				Ok(Some(relay_finality_pre_dispatch_data()),)
2358			);
2359			assert_eq!(
2360				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(200, 200)),
2361				Ok(Some(relay_finality_pre_dispatch_data_ex()),)
2362			);
2363			assert_eq!(
2364				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 200)),
2365				Ok(Some(relay_finality_confirmation_pre_dispatch_data())),
2366			);
2367			assert_eq!(
2368				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call_ex(200, 200)),
2369				Ok(Some(relay_finality_confirmation_pre_dispatch_data_ex())),
2370			);
2371
2372			assert_eq!(
2373				run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 200)),
2374				Ok(Default::default()),
2375			);
2376			assert_eq!(
2377				run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(200, 200)),
2378				Ok(Default::default()),
2379			);
2380			assert_eq!(
2381				run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 200)),
2382				Ok(Default::default()),
2383			);
2384			assert_eq!(
2385				run_grandpa_validate(relay_finality_and_confirmation_batch_call_ex(200, 200)),
2386				Ok(Default::default()),
2387			);
2388
2389			assert_eq!(
2390				run_grandpa_pre_dispatch(message_delivery_call(200)),
2391				Ok(Some(delivery_pre_dispatch_data())),
2392			);
2393			assert_eq!(
2394				run_grandpa_pre_dispatch(message_confirmation_call(200)),
2395				Ok(Some(confirmation_pre_dispatch_data())),
2396			);
2397
2398			assert_eq!(run_grandpa_validate(message_delivery_call(200)), Ok(Default::default()),);
2399			assert_eq!(
2400				run_grandpa_validate(message_confirmation_call(200)),
2401				Ok(Default::default()),
2402			);
2403		});
2404	}
2405
2406	#[test]
2407	fn does_not_panic_on_boosting_priority_of_empty_message_delivery_transaction() {
2408		run_test(|| {
2409			let best_delivered_message =
2410				BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
2411			initialize_environment(100, 100, best_delivered_message);
2412
2413			// register relayer so it gets priority boost
2414			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
2415				.unwrap();
2416
2417			// allow empty message delivery transactions
2418			let lane_id = test_lane_id();
2419			let in_lane_data = InboundLaneData {
2420				last_confirmed_nonce: 0,
2421				relayers: vec![UnrewardedRelayer {
2422					relayer: relayer_account_at_bridged_chain(),
2423					messages: DeliveredMessages { begin: 1, end: best_delivered_message },
2424				}]
2425				.into(),
2426				..Default::default()
2427			};
2428			pallet_bridge_messages::InboundLanes::<TestRuntime>::insert(lane_id, in_lane_data);
2429
2430			// now check that the priority of empty tx is the same as priority of 1-message tx
2431			let priority_of_zero_messages_delivery =
2432				run_validate(message_delivery_call(best_delivered_message)).unwrap().priority;
2433			let priority_of_one_messages_delivery =
2434				run_validate(message_delivery_call(best_delivered_message + 1))
2435					.unwrap()
2436					.priority;
2437
2438			assert_eq!(priority_of_zero_messages_delivery, priority_of_one_messages_delivery);
2439		});
2440	}
2441}