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, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
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, RuntimeDebug,
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(RuntimeDebug, 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	RuntimeDebugNoBound,
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		Ok(Weight::zero())
418	}
419}
420
421/// Verify that the messages pallet call, supported by extension has succeeded.
422pub(crate) fn verify_messages_call_succeeded<C>(
423	call_info: &ExtensionCallInfo<
424		C::RemoteGrandpaChainBlockNumber,
425		LaneIdOf<C::Runtime, C::BridgeMessagesPalletInstance>,
426	>,
427	_call_data: &mut ExtensionCallData,
428	relayer: &<C::Runtime as SystemConfig>::AccountId,
429) -> bool
430where
431	C: ExtensionConfig,
432	C::Runtime: BridgeMessagesConfig<C::BridgeMessagesPalletInstance>,
433{
434	let messages_call = call_info.messages_call_info();
435
436	if !MessagesCallHelper::<C::Runtime, C::BridgeMessagesPalletInstance>::was_successful(
437		messages_call,
438	) {
439		tracing::trace!(
440			target: LOG_TARGET,
441			id_provider=%C::IdProvider::STR,
442			lane_id=?call_info.messages_call_info().lane_id(),
443			?relayer,
444			"Relayer has submitted invalid messages call"
445		);
446		return false
447	}
448
449	true
450}
451
452#[cfg(test)]
453mod tests {
454	use super::*;
455	use crate::mock::*;
456
457	use bp_header_chain::{StoredHeaderDataBuilder, SubmitFinalityProofInfo};
458	use bp_messages::{
459		source_chain::FromBridgedChainMessagesDeliveryProof,
460		target_chain::FromBridgedChainMessagesProof, BaseMessagesProofInfo, DeliveredMessages,
461		InboundLaneData, MessageNonce, MessagesCallInfo, MessagesOperatingMode, OutboundLaneData,
462		ReceiveMessagesDeliveryProofInfo, ReceiveMessagesProofInfo, UnrewardedRelayer,
463		UnrewardedRelayerOccupation, UnrewardedRelayersState,
464	};
465	use bp_parachains::{BestParaHeadHash, ParaInfo, SubmitParachainHeadsInfo};
466	use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId};
467	use bp_relayers::RuntimeWithUtilityPallet;
468	use bp_runtime::{BasicOperatingMode, HeaderId, Parachain};
469	use bp_test_utils::{make_default_justification, test_keyring, TEST_GRANDPA_SET_ID};
470	use frame_support::{
471		__private::sp_tracing,
472		assert_storage_noop, parameter_types,
473		traits::{fungible::Mutate, ReservableCurrency},
474		weights::Weight,
475	};
476	use pallet_bridge_grandpa::{Call as GrandpaCall, Pallet as GrandpaPallet, StoredAuthoritySet};
477	use pallet_bridge_messages::{Call as MessagesCall, Pallet as MessagesPallet};
478	use pallet_bridge_parachains::{Call as ParachainsCall, Pallet as ParachainsPallet};
479	use pallet_utility::Call as UtilityCall;
480	use sp_runtime::{
481		traits::{ConstU64, DispatchTransaction, Header as HeaderT},
482		transaction_validity::{
483			InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction,
484		},
485		DispatchError,
486	};
487
488	parameter_types! {
489		TestParachain: u32 = BridgedUnderlyingParachain::PARACHAIN_ID;
490		pub MsgProofsRewardsAccount: RewardsAccountParams<TestLaneIdType> = RewardsAccountParams::new(
491			test_lane_id(),
492			TEST_BRIDGED_CHAIN_ID,
493			RewardsAccountOwner::ThisChain,
494		);
495		pub MsgDeliveryProofsRewardsAccount: RewardsAccountParams<TestLaneIdType> = RewardsAccountParams::new(
496			test_lane_id(),
497			TEST_BRIDGED_CHAIN_ID,
498			RewardsAccountOwner::BridgedChain,
499		);
500	}
501
502	bp_runtime::generate_static_str_provider!(TestGrandpaExtension);
503	bp_runtime::generate_static_str_provider!(TestExtension);
504	bp_runtime::generate_static_str_provider!(TestMessagesExtension);
505
506	type TestGrandpaExtensionConfig = grandpa_adapter::WithGrandpaChainExtensionConfig<
507		StrTestGrandpaExtension,
508		TestRuntime,
509		RuntimeWithUtilityPallet<TestRuntime>,
510		(),
511		(),
512		(),
513		ConstU64<1>,
514	>;
515	type TestGrandpaExtension =
516		BridgeRelayersTransactionExtension<TestRuntime, TestGrandpaExtensionConfig>;
517	type TestExtensionConfig = parachain_adapter::WithParachainExtensionConfig<
518		StrTestExtension,
519		TestRuntime,
520		RuntimeWithUtilityPallet<TestRuntime>,
521		(),
522		(),
523		(),
524		ConstU64<1>,
525	>;
526	type TestExtension = BridgeRelayersTransactionExtension<TestRuntime, TestExtensionConfig>;
527	type TestMessagesExtensionConfig = messages_adapter::WithMessagesExtensionConfig<
528		StrTestMessagesExtension,
529		TestRuntime,
530		(),
531		(),
532		ConstU64<1>,
533	>;
534	type TestMessagesExtension =
535		BridgeRelayersTransactionExtension<TestRuntime, TestMessagesExtensionConfig>;
536
537	fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance {
538		let test_stake: ThisChainBalance = Stake::get();
539		ExistentialDeposit::get().saturating_add(test_stake * 100)
540	}
541
542	// in tests, the following accounts are equal (because of how `into_sub_account_truncating`
543	// works)
544
545	fn delivery_rewards_account() -> ThisChainAccountId {
546		TestPaymentProcedure::rewards_account(MsgProofsRewardsAccount::get())
547	}
548
549	fn confirmation_rewards_account() -> ThisChainAccountId {
550		TestPaymentProcedure::rewards_account(MsgDeliveryProofsRewardsAccount::get())
551	}
552
553	fn relayer_account_at_this_chain() -> ThisChainAccountId {
554		0
555	}
556
557	fn relayer_account_at_bridged_chain() -> BridgedChainAccountId {
558		0
559	}
560
561	fn initialize_environment(
562		best_relay_header_number: BridgedChainBlockNumber,
563		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
564		best_message: MessageNonce,
565	) {
566		let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect();
567		let best_relay_header = HeaderId(best_relay_header_number, BridgedChainHash::default());
568		pallet_bridge_grandpa::CurrentAuthoritySet::<TestRuntime>::put(
569			StoredAuthoritySet::try_new(authorities, TEST_GRANDPA_SET_ID).unwrap(),
570		);
571		pallet_bridge_grandpa::BestFinalized::<TestRuntime>::put(best_relay_header);
572		pallet_bridge_grandpa::ImportedHeaders::<TestRuntime>::insert(
573			best_relay_header.hash(),
574			bp_test_utils::test_header::<BridgedChainHeader>(0).build(),
575		);
576
577		let para_id = ParaId(TestParachain::get());
578		let para_info = ParaInfo {
579			best_head_hash: BestParaHeadHash {
580				at_relay_block_number: parachain_head_at_relay_header_number,
581				head_hash: [parachain_head_at_relay_header_number as u8; 32].into(),
582			},
583			next_imported_hash_position: 0,
584		};
585		pallet_bridge_parachains::ParasInfo::<TestRuntime>::insert(para_id, para_info);
586
587		let lane_id = test_lane_id();
588		let in_lane_data =
589			InboundLaneData { last_confirmed_nonce: best_message, ..Default::default() };
590		pallet_bridge_messages::InboundLanes::<TestRuntime>::insert(lane_id, in_lane_data);
591
592		let out_lane_data =
593			OutboundLaneData { latest_received_nonce: best_message, ..Default::default() };
594		pallet_bridge_messages::OutboundLanes::<TestRuntime>::insert(lane_id, out_lane_data);
595
596		Balances::mint_into(&delivery_rewards_account(), ExistentialDeposit::get()).unwrap();
597		Balances::mint_into(&confirmation_rewards_account(), ExistentialDeposit::get()).unwrap();
598		Balances::mint_into(
599			&relayer_account_at_this_chain(),
600			initial_balance_of_relayer_account_at_this_chain(),
601		)
602		.unwrap();
603	}
604
605	fn submit_relay_header_call(relay_header_number: BridgedChainBlockNumber) -> RuntimeCall {
606		let relay_header = BridgedChainHeader::new(
607			relay_header_number,
608			Default::default(),
609			Default::default(),
610			Default::default(),
611			Default::default(),
612		);
613		let relay_justification = make_default_justification(&relay_header);
614
615		RuntimeCall::BridgeGrandpa(GrandpaCall::submit_finality_proof {
616			finality_target: Box::new(relay_header),
617			justification: relay_justification,
618		})
619	}
620
621	fn submit_relay_header_call_ex(relay_header_number: BridgedChainBlockNumber) -> RuntimeCall {
622		let relay_header = BridgedChainHeader::new(
623			relay_header_number,
624			Default::default(),
625			Default::default(),
626			Default::default(),
627			Default::default(),
628		);
629		let relay_justification = make_default_justification(&relay_header);
630
631		RuntimeCall::BridgeGrandpa(GrandpaCall::submit_finality_proof_ex {
632			finality_target: Box::new(relay_header),
633			justification: relay_justification,
634			current_set_id: TEST_GRANDPA_SET_ID,
635			is_free_execution_expected: false,
636		})
637	}
638
639	fn submit_parachain_head_call(
640		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
641	) -> RuntimeCall {
642		RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads {
643			at_relay_block: (parachain_head_at_relay_header_number, BridgedChainHash::default()),
644			parachains: vec![(
645				ParaId(TestParachain::get()),
646				[parachain_head_at_relay_header_number as u8; 32].into(),
647			)],
648			parachain_heads_proof: ParaHeadsProof { storage_proof: Default::default() },
649		})
650	}
651
652	pub fn submit_parachain_head_call_ex(
653		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
654	) -> RuntimeCall {
655		RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads_ex {
656			at_relay_block: (parachain_head_at_relay_header_number, BridgedChainHash::default()),
657			parachains: vec![(
658				ParaId(TestParachain::get()),
659				[parachain_head_at_relay_header_number as u8; 32].into(),
660			)],
661			parachain_heads_proof: ParaHeadsProof { storage_proof: Default::default() },
662			is_free_execution_expected: false,
663		})
664	}
665
666	fn message_delivery_call(best_message: MessageNonce) -> RuntimeCall {
667		RuntimeCall::BridgeMessages(MessagesCall::receive_messages_proof {
668			relayer_id_at_bridged_chain: relayer_account_at_bridged_chain(),
669			proof: Box::new(FromBridgedChainMessagesProof {
670				bridged_header_hash: Default::default(),
671				storage_proof: Default::default(),
672				lane: test_lane_id(),
673				nonces_start: pallet_bridge_messages::InboundLanes::<TestRuntime>::get(
674					test_lane_id(),
675				)
676				.unwrap()
677				.last_delivered_nonce() +
678					1,
679				nonces_end: best_message,
680			}),
681			messages_count: 1,
682			dispatch_weight: Weight::zero(),
683		})
684	}
685
686	fn message_confirmation_call(best_message: MessageNonce) -> RuntimeCall {
687		RuntimeCall::BridgeMessages(MessagesCall::receive_messages_delivery_proof {
688			proof: FromBridgedChainMessagesDeliveryProof {
689				bridged_header_hash: Default::default(),
690				storage_proof: Default::default(),
691				lane: test_lane_id(),
692			},
693			relayers_state: UnrewardedRelayersState {
694				last_delivered_nonce: best_message,
695				..Default::default()
696			},
697		})
698	}
699
700	fn parachain_finality_and_delivery_batch_call(
701		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
702		best_message: MessageNonce,
703	) -> RuntimeCall {
704		RuntimeCall::Utility(UtilityCall::batch_all {
705			calls: vec![
706				submit_parachain_head_call(parachain_head_at_relay_header_number),
707				message_delivery_call(best_message),
708			],
709		})
710	}
711
712	fn parachain_finality_and_confirmation_batch_call(
713		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
714		best_message: MessageNonce,
715	) -> RuntimeCall {
716		RuntimeCall::Utility(UtilityCall::batch_all {
717			calls: vec![
718				submit_parachain_head_call(parachain_head_at_relay_header_number),
719				message_confirmation_call(best_message),
720			],
721		})
722	}
723
724	fn relay_finality_and_delivery_batch_call(
725		relay_header_number: BridgedChainBlockNumber,
726		best_message: MessageNonce,
727	) -> RuntimeCall {
728		RuntimeCall::Utility(UtilityCall::batch_all {
729			calls: vec![
730				submit_relay_header_call(relay_header_number),
731				message_delivery_call(best_message),
732			],
733		})
734	}
735
736	fn relay_finality_and_delivery_batch_call_ex(
737		relay_header_number: BridgedChainBlockNumber,
738		best_message: MessageNonce,
739	) -> RuntimeCall {
740		RuntimeCall::Utility(UtilityCall::batch_all {
741			calls: vec![
742				submit_relay_header_call_ex(relay_header_number),
743				message_delivery_call(best_message),
744			],
745		})
746	}
747
748	fn relay_finality_and_confirmation_batch_call(
749		relay_header_number: BridgedChainBlockNumber,
750		best_message: MessageNonce,
751	) -> RuntimeCall {
752		RuntimeCall::Utility(UtilityCall::batch_all {
753			calls: vec![
754				submit_relay_header_call(relay_header_number),
755				message_confirmation_call(best_message),
756			],
757		})
758	}
759
760	fn relay_finality_and_confirmation_batch_call_ex(
761		relay_header_number: BridgedChainBlockNumber,
762		best_message: MessageNonce,
763	) -> RuntimeCall {
764		RuntimeCall::Utility(UtilityCall::batch_all {
765			calls: vec![
766				submit_relay_header_call_ex(relay_header_number),
767				message_confirmation_call(best_message),
768			],
769		})
770	}
771
772	fn all_finality_and_delivery_batch_call(
773		relay_header_number: BridgedChainBlockNumber,
774		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
775		best_message: MessageNonce,
776	) -> RuntimeCall {
777		RuntimeCall::Utility(UtilityCall::batch_all {
778			calls: vec![
779				submit_relay_header_call(relay_header_number),
780				submit_parachain_head_call(parachain_head_at_relay_header_number),
781				message_delivery_call(best_message),
782			],
783		})
784	}
785
786	fn all_finality_and_delivery_batch_call_ex(
787		relay_header_number: BridgedChainBlockNumber,
788		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
789		best_message: MessageNonce,
790	) -> RuntimeCall {
791		RuntimeCall::Utility(UtilityCall::batch_all {
792			calls: vec![
793				submit_relay_header_call_ex(relay_header_number),
794				submit_parachain_head_call_ex(parachain_head_at_relay_header_number),
795				message_delivery_call(best_message),
796			],
797		})
798	}
799
800	fn all_finality_and_confirmation_batch_call(
801		relay_header_number: BridgedChainBlockNumber,
802		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
803		best_message: MessageNonce,
804	) -> RuntimeCall {
805		RuntimeCall::Utility(UtilityCall::batch_all {
806			calls: vec![
807				submit_relay_header_call(relay_header_number),
808				submit_parachain_head_call(parachain_head_at_relay_header_number),
809				message_confirmation_call(best_message),
810			],
811		})
812	}
813
814	fn all_finality_and_confirmation_batch_call_ex(
815		relay_header_number: BridgedChainBlockNumber,
816		parachain_head_at_relay_header_number: BridgedChainBlockNumber,
817		best_message: MessageNonce,
818	) -> RuntimeCall {
819		RuntimeCall::Utility(UtilityCall::batch_all {
820			calls: vec![
821				submit_relay_header_call_ex(relay_header_number),
822				submit_parachain_head_call_ex(parachain_head_at_relay_header_number),
823				message_confirmation_call(best_message),
824			],
825		})
826	}
827
828	fn all_finality_pre_dispatch_data(
829	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
830		PreDispatchData {
831			relayer: relayer_account_at_this_chain(),
832			call_info: ExtensionCallInfo::AllFinalityAndMsgs(
833				SubmitFinalityProofInfo {
834					block_number: 200,
835					current_set_id: None,
836					extra_weight: Weight::zero(),
837					extra_size: 0,
838					is_mandatory: false,
839					is_free_execution_expected: false,
840				},
841				SubmitParachainHeadsInfo {
842					at_relay_block: HeaderId(200, [0u8; 32].into()),
843					para_id: ParaId(TestParachain::get()),
844					para_head_hash: [200u8; 32].into(),
845					is_free_execution_expected: false,
846				},
847				MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo {
848					base: BaseMessagesProofInfo {
849						lane_id: test_lane_id(),
850						bundled_range: 101..=200,
851						best_stored_nonce: 100,
852					},
853					unrewarded_relayers: UnrewardedRelayerOccupation {
854						free_relayer_slots:
855							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
856						free_message_slots:
857							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
858					},
859				}),
860			),
861		}
862	}
863
864	#[cfg(test)]
865	fn all_finality_pre_dispatch_data_ex(
866	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
867		let mut data = all_finality_pre_dispatch_data();
868		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
869		data
870	}
871
872	fn all_finality_confirmation_pre_dispatch_data(
873	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
874		PreDispatchData {
875			relayer: relayer_account_at_this_chain(),
876			call_info: ExtensionCallInfo::AllFinalityAndMsgs(
877				SubmitFinalityProofInfo {
878					block_number: 200,
879					current_set_id: None,
880					extra_weight: Weight::zero(),
881					extra_size: 0,
882					is_mandatory: false,
883					is_free_execution_expected: false,
884				},
885				SubmitParachainHeadsInfo {
886					at_relay_block: HeaderId(200, [0u8; 32].into()),
887					para_id: ParaId(TestParachain::get()),
888					para_head_hash: [200u8; 32].into(),
889					is_free_execution_expected: false,
890				},
891				MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
892					BaseMessagesProofInfo {
893						lane_id: test_lane_id(),
894						bundled_range: 101..=200,
895						best_stored_nonce: 100,
896					},
897				)),
898			),
899		}
900	}
901
902	fn all_finality_confirmation_pre_dispatch_data_ex(
903	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
904		let mut data = all_finality_confirmation_pre_dispatch_data();
905		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
906		data
907	}
908
909	fn relay_finality_pre_dispatch_data(
910	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
911		PreDispatchData {
912			relayer: relayer_account_at_this_chain(),
913			call_info: ExtensionCallInfo::RelayFinalityAndMsgs(
914				SubmitFinalityProofInfo {
915					block_number: 200,
916					current_set_id: None,
917					extra_weight: Weight::zero(),
918					extra_size: 0,
919					is_mandatory: false,
920					is_free_execution_expected: false,
921				},
922				MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo {
923					base: BaseMessagesProofInfo {
924						lane_id: test_lane_id(),
925						bundled_range: 101..=200,
926						best_stored_nonce: 100,
927					},
928					unrewarded_relayers: UnrewardedRelayerOccupation {
929						free_relayer_slots:
930							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
931						free_message_slots:
932							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
933					},
934				}),
935			),
936		}
937	}
938
939	fn relay_finality_pre_dispatch_data_ex(
940	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
941		let mut data = relay_finality_pre_dispatch_data();
942		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
943		data
944	}
945
946	fn relay_finality_confirmation_pre_dispatch_data(
947	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
948		PreDispatchData {
949			relayer: relayer_account_at_this_chain(),
950			call_info: ExtensionCallInfo::RelayFinalityAndMsgs(
951				SubmitFinalityProofInfo {
952					block_number: 200,
953					current_set_id: None,
954					extra_weight: Weight::zero(),
955					extra_size: 0,
956					is_mandatory: false,
957					is_free_execution_expected: false,
958				},
959				MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
960					BaseMessagesProofInfo {
961						lane_id: test_lane_id(),
962						bundled_range: 101..=200,
963						best_stored_nonce: 100,
964					},
965				)),
966			),
967		}
968	}
969
970	fn relay_finality_confirmation_pre_dispatch_data_ex(
971	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
972		let mut data = relay_finality_confirmation_pre_dispatch_data();
973		data.submit_finality_proof_info_mut().unwrap().current_set_id = Some(TEST_GRANDPA_SET_ID);
974		data
975	}
976
977	fn parachain_finality_pre_dispatch_data(
978	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
979		PreDispatchData {
980			relayer: relayer_account_at_this_chain(),
981			call_info: ExtensionCallInfo::ParachainFinalityAndMsgs(
982				SubmitParachainHeadsInfo {
983					at_relay_block: HeaderId(200, [0u8; 32].into()),
984					para_id: ParaId(TestParachain::get()),
985					para_head_hash: [200u8; 32].into(),
986					is_free_execution_expected: false,
987				},
988				MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo {
989					base: BaseMessagesProofInfo {
990						lane_id: test_lane_id(),
991						bundled_range: 101..=200,
992						best_stored_nonce: 100,
993					},
994					unrewarded_relayers: UnrewardedRelayerOccupation {
995						free_relayer_slots:
996							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
997						free_message_slots:
998							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
999					},
1000				}),
1001			),
1002		}
1003	}
1004
1005	fn parachain_finality_confirmation_pre_dispatch_data(
1006	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
1007		PreDispatchData {
1008			relayer: relayer_account_at_this_chain(),
1009			call_info: ExtensionCallInfo::ParachainFinalityAndMsgs(
1010				SubmitParachainHeadsInfo {
1011					at_relay_block: HeaderId(200, [0u8; 32].into()),
1012					para_id: ParaId(TestParachain::get()),
1013					para_head_hash: [200u8; 32].into(),
1014					is_free_execution_expected: false,
1015				},
1016				MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo(
1017					BaseMessagesProofInfo {
1018						lane_id: test_lane_id(),
1019						bundled_range: 101..=200,
1020						best_stored_nonce: 100,
1021					},
1022				)),
1023			),
1024		}
1025	}
1026
1027	fn delivery_pre_dispatch_data<RemoteGrandpaChainBlockNumber: Debug>(
1028	) -> PreDispatchData<ThisChainAccountId, RemoteGrandpaChainBlockNumber, TestLaneIdType> {
1029		PreDispatchData {
1030			relayer: relayer_account_at_this_chain(),
1031			call_info: ExtensionCallInfo::Msgs(MessagesCallInfo::ReceiveMessagesProof(
1032				ReceiveMessagesProofInfo {
1033					base: BaseMessagesProofInfo {
1034						lane_id: test_lane_id(),
1035						bundled_range: 101..=200,
1036						best_stored_nonce: 100,
1037					},
1038					unrewarded_relayers: UnrewardedRelayerOccupation {
1039						free_relayer_slots:
1040							BridgedUnderlyingParachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
1041						free_message_slots:
1042							BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
1043					},
1044				},
1045			)),
1046		}
1047	}
1048
1049	fn confirmation_pre_dispatch_data<RemoteGrandpaChainBlockNumber: Debug>(
1050	) -> PreDispatchData<ThisChainAccountId, RemoteGrandpaChainBlockNumber, TestLaneIdType> {
1051		PreDispatchData {
1052			relayer: relayer_account_at_this_chain(),
1053			call_info: ExtensionCallInfo::Msgs(MessagesCallInfo::ReceiveMessagesDeliveryProof(
1054				ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo {
1055					lane_id: test_lane_id(),
1056					bundled_range: 101..=200,
1057					best_stored_nonce: 100,
1058				}),
1059			)),
1060		}
1061	}
1062
1063	fn set_bundled_range_end(
1064		mut pre_dispatch_data: PreDispatchData<
1065			ThisChainAccountId,
1066			BridgedChainBlockNumber,
1067			TestLaneIdType,
1068		>,
1069		end: MessageNonce,
1070	) -> PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType> {
1071		let msg_info = match pre_dispatch_data.call_info {
1072			ExtensionCallInfo::AllFinalityAndMsgs(_, _, ref mut info) => info,
1073			ExtensionCallInfo::RelayFinalityAndMsgs(_, ref mut info) => info,
1074			ExtensionCallInfo::ParachainFinalityAndMsgs(_, ref mut info) => info,
1075			ExtensionCallInfo::Msgs(ref mut info) => info,
1076		};
1077
1078		if let MessagesCallInfo::ReceiveMessagesProof(ref mut msg_info) = msg_info {
1079			msg_info.base.bundled_range = *msg_info.base.bundled_range.start()..=end
1080		}
1081
1082		pre_dispatch_data
1083	}
1084
1085	fn run_validate(call: RuntimeCall) -> TransactionValidity {
1086		let extension: TestExtension = BridgeRelayersTransactionExtension(PhantomData);
1087		extension
1088			.validate_only(
1089				Some(relayer_account_at_this_chain()).into(),
1090				&call,
1091				&DispatchInfo::default(),
1092				0,
1093				External,
1094				0,
1095			)
1096			.map(|t| t.0)
1097	}
1098
1099	fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity {
1100		let extension: TestGrandpaExtension = BridgeRelayersTransactionExtension(PhantomData);
1101		extension
1102			.validate_only(
1103				Some(relayer_account_at_this_chain()).into(),
1104				&call,
1105				&DispatchInfo::default(),
1106				0,
1107				External,
1108				0,
1109			)
1110			.map(|t| t.0)
1111	}
1112
1113	fn run_messages_validate(call: RuntimeCall) -> TransactionValidity {
1114		let extension: TestMessagesExtension = BridgeRelayersTransactionExtension(PhantomData);
1115		extension
1116			.validate_only(
1117				Some(relayer_account_at_this_chain()).into(),
1118				&call,
1119				&DispatchInfo::default(),
1120				0,
1121				External,
1122				0,
1123			)
1124			.map(|t| t.0)
1125	}
1126
1127	fn ignore_priority(tx: TransactionValidity) -> TransactionValidity {
1128		tx.map(|mut tx| {
1129			tx.priority = 0;
1130			tx
1131		})
1132	}
1133
1134	fn run_pre_dispatch(
1135		call: RuntimeCall,
1136	) -> Result<
1137		Option<PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType>>,
1138		TransactionValidityError,
1139	> {
1140		sp_tracing::try_init_simple();
1141		let extension: TestExtension = BridgeRelayersTransactionExtension(PhantomData);
1142		extension
1143			.validate_and_prepare(
1144				Some(relayer_account_at_this_chain()).into(),
1145				&call,
1146				&DispatchInfo::default(),
1147				0,
1148				0,
1149			)
1150			.map(|(pre, _)| pre)
1151	}
1152
1153	fn run_grandpa_pre_dispatch(
1154		call: RuntimeCall,
1155	) -> Result<
1156		Option<PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType>>,
1157		TransactionValidityError,
1158	> {
1159		let extension: TestGrandpaExtension = BridgeRelayersTransactionExtension(PhantomData);
1160		extension
1161			.validate_and_prepare(
1162				Some(relayer_account_at_this_chain()).into(),
1163				&call,
1164				&DispatchInfo::default(),
1165				0,
1166				0,
1167			)
1168			.map(|(pre, _)| pre)
1169	}
1170
1171	fn run_messages_pre_dispatch(
1172		call: RuntimeCall,
1173	) -> Result<
1174		Option<PreDispatchData<ThisChainAccountId, (), TestLaneIdType>>,
1175		TransactionValidityError,
1176	> {
1177		let extension: TestMessagesExtension = BridgeRelayersTransactionExtension(PhantomData);
1178		extension
1179			.validate_and_prepare(
1180				Some(relayer_account_at_this_chain()).into(),
1181				&call,
1182				&DispatchInfo::default(),
1183				0,
1184				0,
1185			)
1186			.map(|(pre, _)| pre)
1187	}
1188
1189	fn dispatch_info() -> DispatchInfo {
1190		DispatchInfo {
1191			call_weight: Weight::from_parts(
1192				frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND,
1193				0,
1194			),
1195			extension_weight: Weight::zero(),
1196			class: frame_support::dispatch::DispatchClass::Normal,
1197			pays_fee: frame_support::dispatch::Pays::Yes,
1198		}
1199	}
1200
1201	fn post_dispatch_info() -> PostDispatchInfo {
1202		PostDispatchInfo { actual_weight: None, pays_fee: frame_support::dispatch::Pays::Yes }
1203	}
1204
1205	fn run_post_dispatch(
1206		pre_dispatch_data: Option<
1207			PreDispatchData<ThisChainAccountId, BridgedChainBlockNumber, TestLaneIdType>,
1208		>,
1209		dispatch_result: DispatchResult,
1210	) {
1211		let post_dispatch_result = TestExtension::post_dispatch_details(
1212			pre_dispatch_data,
1213			&dispatch_info(),
1214			&post_dispatch_info(),
1215			1024,
1216			&dispatch_result,
1217		);
1218		assert_eq!(post_dispatch_result, Ok(Weight::zero()));
1219	}
1220
1221	fn expected_delivery_reward() -> RewardBalance {
1222		let mut post_dispatch_info = post_dispatch_info();
1223		let extra_weight = <TestRuntime as RelayersConfig>::WeightInfo::extra_weight_of_successful_receive_messages_proof_call();
1224		post_dispatch_info.actual_weight =
1225			Some(dispatch_info().call_weight.saturating_sub(extra_weight));
1226		pallet_transaction_payment::Pallet::<TestRuntime>::compute_actual_fee(
1227			1024,
1228			&dispatch_info(),
1229			&post_dispatch_info,
1230			Zero::zero(),
1231		)
1232	}
1233
1234	fn expected_confirmation_reward() -> RewardBalance {
1235		pallet_transaction_payment::Pallet::<TestRuntime>::compute_actual_fee(
1236			1024,
1237			&dispatch_info(),
1238			&post_dispatch_info(),
1239			Zero::zero(),
1240		)
1241	}
1242
1243	#[test]
1244	fn validate_doesnt_boost_transaction_priority_if_relayer_is_not_registered() {
1245		run_test(|| {
1246			initialize_environment(100, 100, 100);
1247			Balances::set_balance(&relayer_account_at_this_chain(), ExistentialDeposit::get());
1248
1249			// message delivery is failing
1250			assert_eq!(run_validate(message_delivery_call(200)), Ok(Default::default()),);
1251			assert_eq!(
1252				run_validate(parachain_finality_and_delivery_batch_call(200, 200)),
1253				Ok(Default::default()),
1254			);
1255			assert_eq!(
1256				run_validate(all_finality_and_delivery_batch_call(200, 200, 200)),
1257				Ok(Default::default()),
1258			);
1259			// message confirmation validation is passing
1260			assert_eq!(
1261				ignore_priority(run_validate(message_confirmation_call(200))),
1262				Ok(Default::default()),
1263			);
1264			assert_eq!(
1265				ignore_priority(run_validate(parachain_finality_and_confirmation_batch_call(
1266					200, 200
1267				))),
1268				Ok(Default::default()),
1269			);
1270			assert_eq!(
1271				ignore_priority(run_validate(all_finality_and_confirmation_batch_call(
1272					200, 200, 200
1273				))),
1274				Ok(Default::default()),
1275			);
1276		});
1277	}
1278
1279	#[test]
1280	fn validate_boosts_priority_of_message_delivery_transactions() {
1281		run_test(|| {
1282			initialize_environment(100, 100, 100);
1283
1284			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1285				.unwrap();
1286
1287			let priority_of_100_messages_delivery =
1288				run_validate(message_delivery_call(200)).unwrap().priority;
1289			let priority_of_200_messages_delivery =
1290				run_validate(message_delivery_call(300)).unwrap().priority;
1291			assert!(
1292				priority_of_200_messages_delivery > priority_of_100_messages_delivery,
1293				"Invalid priorities: {} for 200 messages vs {} for 100 messages",
1294				priority_of_200_messages_delivery,
1295				priority_of_100_messages_delivery,
1296			);
1297
1298			let priority_of_100_messages_confirmation =
1299				run_validate(message_confirmation_call(200)).unwrap().priority;
1300			let priority_of_200_messages_confirmation =
1301				run_validate(message_confirmation_call(300)).unwrap().priority;
1302			assert_eq!(
1303				priority_of_100_messages_confirmation,
1304				priority_of_200_messages_confirmation
1305			);
1306		});
1307	}
1308
1309	#[test]
1310	fn validate_does_not_boost_priority_of_message_delivery_transactions_with_too_many_messages() {
1311		run_test(|| {
1312			initialize_environment(100, 100, 100);
1313
1314			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1315				.unwrap();
1316
1317			let priority_of_max_messages_delivery = run_validate(message_delivery_call(
1318				100 + BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
1319			))
1320			.unwrap()
1321			.priority;
1322			let priority_of_more_than_max_messages_delivery = run_validate(message_delivery_call(
1323				100 + BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX + 1,
1324			))
1325			.unwrap()
1326			.priority;
1327
1328			assert!(
1329				priority_of_max_messages_delivery > priority_of_more_than_max_messages_delivery,
1330				"Invalid priorities: {} for MAX messages vs {} for MAX+1 messages",
1331				priority_of_max_messages_delivery,
1332				priority_of_more_than_max_messages_delivery,
1333			);
1334		});
1335	}
1336
1337	#[test]
1338	fn validate_allows_non_obsolete_transactions() {
1339		run_test(|| {
1340			initialize_environment(100, 100, 100);
1341
1342			assert_eq!(
1343				ignore_priority(run_validate(message_delivery_call(200))),
1344				Ok(ValidTransaction::default()),
1345			);
1346			assert_eq!(
1347				ignore_priority(run_validate(message_confirmation_call(200))),
1348				Ok(ValidTransaction::default()),
1349			);
1350			assert_eq!(
1351				ignore_priority(run_messages_validate(message_delivery_call(200))),
1352				Ok(ValidTransaction::default()),
1353			);
1354
1355			assert_eq!(
1356				ignore_priority(run_validate(parachain_finality_and_delivery_batch_call(200, 200))),
1357				Ok(ValidTransaction::default()),
1358			);
1359			assert_eq!(
1360				ignore_priority(run_validate(parachain_finality_and_confirmation_batch_call(
1361					200, 200
1362				))),
1363				Ok(ValidTransaction::default()),
1364			);
1365
1366			assert_eq!(
1367				ignore_priority(run_validate(all_finality_and_delivery_batch_call(200, 200, 200))),
1368				Ok(ValidTransaction::default()),
1369			);
1370			assert_eq!(
1371				ignore_priority(run_validate(all_finality_and_confirmation_batch_call(
1372					200, 200, 200
1373				))),
1374				Ok(ValidTransaction::default()),
1375			);
1376		});
1377	}
1378
1379	#[test]
1380	fn ext_rejects_batch_with_obsolete_relay_chain_header() {
1381		run_test(|| {
1382			initialize_environment(100, 100, 100);
1383
1384			assert_eq!(
1385				run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)),
1386				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1387			);
1388			assert_eq!(
1389				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(100, 200, 200)),
1390				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1391			);
1392
1393			assert_eq!(
1394				run_validate(all_finality_and_delivery_batch_call(100, 200, 200)),
1395				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1396			);
1397			assert_eq!(
1398				run_validate(all_finality_and_delivery_batch_call_ex(100, 200, 200)),
1399				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1400			);
1401		});
1402	}
1403
1404	#[test]
1405	fn ext_rejects_batch_with_obsolete_parachain_head() {
1406		run_test(|| {
1407			initialize_environment(100, 100, 100);
1408
1409			assert_eq!(
1410				run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)),
1411				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1412			);
1413			assert_eq!(
1414				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(101, 100, 200)),
1415				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1416			);
1417			assert_eq!(
1418				run_validate(all_finality_and_delivery_batch_call(101, 100, 200)),
1419				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1420			);
1421			assert_eq!(
1422				run_validate(all_finality_and_delivery_batch_call_ex(101, 100, 200)),
1423				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1424			);
1425
1426			assert_eq!(
1427				run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)),
1428				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1429			);
1430			assert_eq!(
1431				run_validate(parachain_finality_and_delivery_batch_call(100, 200)),
1432				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1433			);
1434		});
1435	}
1436
1437	#[test]
1438	fn ext_rejects_batch_with_obsolete_messages() {
1439		run_test(|| {
1440			initialize_environment(100, 100, 100);
1441
1442			assert_eq!(
1443				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)),
1444				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1445			);
1446			assert_eq!(
1447				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 100)),
1448				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1449			);
1450			assert_eq!(
1451				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 100)),
1452				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1453			);
1454			assert_eq!(
1455				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 100)),
1456				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1457			);
1458
1459			assert_eq!(
1460				run_validate(all_finality_and_delivery_batch_call(200, 200, 100)),
1461				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1462			);
1463			assert_eq!(
1464				run_validate(all_finality_and_delivery_batch_call_ex(200, 200, 100)),
1465				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1466			);
1467			assert_eq!(
1468				run_validate(all_finality_and_confirmation_batch_call(200, 200, 100)),
1469				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1470			);
1471			assert_eq!(
1472				run_validate(all_finality_and_confirmation_batch_call_ex(200, 200, 100)),
1473				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1474			);
1475
1476			assert_eq!(
1477				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)),
1478				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1479			);
1480			assert_eq!(
1481				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 100)),
1482				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1483			);
1484
1485			assert_eq!(
1486				run_validate(parachain_finality_and_delivery_batch_call(200, 100)),
1487				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1488			);
1489			assert_eq!(
1490				run_validate(parachain_finality_and_confirmation_batch_call(200, 100)),
1491				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
1492			);
1493		});
1494	}
1495
1496	#[test]
1497	fn ext_rejects_batch_with_grandpa_finality_proof_when_grandpa_pallet_is_halted() {
1498		run_test(|| {
1499			initialize_environment(100, 100, 100);
1500
1501			GrandpaPallet::<TestRuntime, ()>::set_operating_mode(
1502				RuntimeOrigin::root(),
1503				BasicOperatingMode::Halted,
1504			)
1505			.unwrap();
1506
1507			assert_eq!(
1508				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1509				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1510			);
1511			assert_eq!(
1512				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1513				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1514			);
1515			assert_eq!(
1516				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1517				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1518			);
1519			assert_eq!(
1520				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1521				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1522			);
1523		});
1524	}
1525
1526	#[test]
1527	fn ext_rejects_batch_with_parachain_finality_proof_when_parachains_pallet_is_halted() {
1528		run_test(|| {
1529			initialize_environment(100, 100, 100);
1530
1531			ParachainsPallet::<TestRuntime, ()>::set_operating_mode(
1532				RuntimeOrigin::root(),
1533				BasicOperatingMode::Halted,
1534			)
1535			.unwrap();
1536
1537			assert_eq!(
1538				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1539				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1540			);
1541			assert_eq!(
1542				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1543				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1544			);
1545			assert_eq!(
1546				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1547				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1548			);
1549			assert_eq!(
1550				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1551				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1552			);
1553
1554			assert_eq!(
1555				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)),
1556				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1557			);
1558			assert_eq!(
1559				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)),
1560				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1561			);
1562		});
1563	}
1564
1565	#[test]
1566	fn ext_rejects_transaction_when_messages_pallet_is_halted() {
1567		run_test(|| {
1568			initialize_environment(100, 100, 100);
1569
1570			MessagesPallet::<TestRuntime, ()>::set_operating_mode(
1571				RuntimeOrigin::root(),
1572				MessagesOperatingMode::Basic(BasicOperatingMode::Halted),
1573			)
1574			.unwrap();
1575
1576			assert_eq!(
1577				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1578				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1579			);
1580			assert_eq!(
1581				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1582				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1583			);
1584			assert_eq!(
1585				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1586				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1587			);
1588			assert_eq!(
1589				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1590				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1591			);
1592
1593			assert_eq!(
1594				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)),
1595				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1596			);
1597			assert_eq!(
1598				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)),
1599				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1600			);
1601
1602			assert_eq!(
1603				run_pre_dispatch(message_delivery_call(200)),
1604				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1605			);
1606			assert_eq!(
1607				run_pre_dispatch(message_confirmation_call(200)),
1608				Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
1609			);
1610		});
1611	}
1612
1613	#[test]
1614	fn pre_dispatch_parses_batch_with_relay_chain_and_parachain_headers() {
1615		run_test(|| {
1616			initialize_environment(100, 100, 100);
1617
1618			assert_eq!(
1619				run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)),
1620				Ok(Some(all_finality_pre_dispatch_data())),
1621			);
1622			assert_eq!(
1623				run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)),
1624				Ok(Some(all_finality_pre_dispatch_data_ex())),
1625			);
1626			assert_eq!(
1627				run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)),
1628				Ok(Some(all_finality_confirmation_pre_dispatch_data())),
1629			);
1630			assert_eq!(
1631				run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)),
1632				Ok(Some(all_finality_confirmation_pre_dispatch_data_ex())),
1633			);
1634		});
1635	}
1636
1637	#[test]
1638	fn pre_dispatch_parses_batch_with_parachain_header() {
1639		run_test(|| {
1640			initialize_environment(100, 100, 100);
1641
1642			assert_eq!(
1643				run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)),
1644				Ok(Some(parachain_finality_pre_dispatch_data())),
1645			);
1646			assert_eq!(
1647				run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)),
1648				Ok(Some(parachain_finality_confirmation_pre_dispatch_data())),
1649			);
1650		});
1651	}
1652
1653	#[test]
1654	fn pre_dispatch_fails_to_parse_batch_with_multiple_parachain_headers() {
1655		run_test(|| {
1656			initialize_environment(100, 100, 100);
1657
1658			let call = RuntimeCall::Utility(UtilityCall::batch_all {
1659				calls: vec![
1660					RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads {
1661						at_relay_block: (100, BridgedChainHash::default()),
1662						parachains: vec![
1663							(ParaId(TestParachain::get()), [1u8; 32].into()),
1664							(ParaId(TestParachain::get() + 1), [1u8; 32].into()),
1665						],
1666						parachain_heads_proof: ParaHeadsProof { storage_proof: Default::default() },
1667					}),
1668					message_delivery_call(200),
1669				],
1670			});
1671
1672			assert_eq!(run_pre_dispatch(call), Ok(None),);
1673		});
1674	}
1675
1676	#[test]
1677	fn pre_dispatch_parses_message_transaction() {
1678		run_test(|| {
1679			initialize_environment(100, 100, 100);
1680
1681			assert_eq!(
1682				run_pre_dispatch(message_delivery_call(200)),
1683				Ok(Some(delivery_pre_dispatch_data())),
1684			);
1685			assert_eq!(
1686				run_pre_dispatch(message_confirmation_call(200)),
1687				Ok(Some(confirmation_pre_dispatch_data())),
1688			);
1689		});
1690	}
1691
1692	#[test]
1693	fn post_dispatch_ignores_unknown_transaction() {
1694		run_test(|| {
1695			assert_storage_noop!(run_post_dispatch(None, Ok(())));
1696		});
1697	}
1698
1699	#[test]
1700	fn post_dispatch_ignores_failed_transaction() {
1701		run_test(|| {
1702			assert_storage_noop!(run_post_dispatch(
1703				Some(all_finality_pre_dispatch_data()),
1704				Err(DispatchError::BadOrigin)
1705			));
1706		});
1707	}
1708
1709	#[test]
1710	fn post_dispatch_ignores_transaction_that_has_not_updated_relay_chain_state() {
1711		run_test(|| {
1712			initialize_environment(100, 200, 200);
1713
1714			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1715		});
1716	}
1717
1718	#[test]
1719	fn post_dispatch_ignores_transaction_that_has_not_updated_parachain_state() {
1720		run_test(|| {
1721			initialize_environment(200, 100, 200);
1722
1723			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1724			assert_storage_noop!(run_post_dispatch(
1725				Some(parachain_finality_pre_dispatch_data()),
1726				Ok(())
1727			));
1728		});
1729	}
1730
1731	#[test]
1732	fn post_dispatch_ignores_transaction_that_has_not_delivered_any_messages() {
1733		run_test(|| {
1734			initialize_environment(200, 200, 100);
1735
1736			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1737			assert_storage_noop!(run_post_dispatch(
1738				Some(parachain_finality_pre_dispatch_data()),
1739				Ok(())
1740			));
1741			assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())));
1742
1743			assert_storage_noop!(run_post_dispatch(
1744				Some(all_finality_confirmation_pre_dispatch_data()),
1745				Ok(())
1746			));
1747			assert_storage_noop!(run_post_dispatch(
1748				Some(parachain_finality_confirmation_pre_dispatch_data()),
1749				Ok(())
1750			));
1751			assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())));
1752		});
1753	}
1754
1755	#[test]
1756	fn post_dispatch_ignores_transaction_that_has_not_delivered_all_messages() {
1757		run_test(|| {
1758			initialize_environment(200, 200, 150);
1759
1760			assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
1761			assert_storage_noop!(run_post_dispatch(
1762				Some(parachain_finality_pre_dispatch_data()),
1763				Ok(())
1764			));
1765			assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())));
1766
1767			assert_storage_noop!(run_post_dispatch(
1768				Some(all_finality_confirmation_pre_dispatch_data()),
1769				Ok(())
1770			));
1771			assert_storage_noop!(run_post_dispatch(
1772				Some(parachain_finality_confirmation_pre_dispatch_data()),
1773				Ok(())
1774			));
1775			assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())));
1776		});
1777	}
1778
1779	#[test]
1780	fn post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight() {
1781		run_test(|| {
1782			initialize_environment(200, 200, 200);
1783
1784			let mut dispatch_info = dispatch_info();
1785			dispatch_info.call_weight = Weight::from_parts(
1786				frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2,
1787				0,
1788			);
1789
1790			// without any size/weight refund: we expect regular reward
1791			let pre_dispatch_data = all_finality_pre_dispatch_data();
1792			let regular_reward = expected_delivery_reward();
1793			run_post_dispatch(Some(pre_dispatch_data), Ok(()));
1794			assert_eq!(
1795				RelayersPallet::<TestRuntime>::relayer_reward(
1796					relayer_account_at_this_chain(),
1797					MsgProofsRewardsAccount::get()
1798				),
1799				Some(regular_reward),
1800			);
1801
1802			// now repeat the same with size+weight refund: we expect smaller reward
1803			let mut pre_dispatch_data = all_finality_pre_dispatch_data();
1804			match pre_dispatch_data.call_info {
1805				ExtensionCallInfo::AllFinalityAndMsgs(ref mut info, ..) => {
1806					info.extra_weight.set_ref_time(
1807						frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND,
1808					);
1809					info.extra_size = 32;
1810				},
1811				_ => unreachable!(),
1812			}
1813			run_post_dispatch(Some(pre_dispatch_data), Ok(()));
1814			let reward_after_two_calls = RelayersPallet::<TestRuntime>::relayer_reward(
1815				relayer_account_at_this_chain(),
1816				MsgProofsRewardsAccount::get(),
1817			)
1818			.unwrap();
1819			assert!(
1820				reward_after_two_calls < 2 * regular_reward,
1821				"{}  must be < 2 * {}",
1822				reward_after_two_calls,
1823				2 * regular_reward,
1824			);
1825		});
1826	}
1827
1828	#[test]
1829	fn post_dispatch_refunds_relayer_in_all_finality_batch() {
1830		run_test(|| {
1831			initialize_environment(200, 200, 200);
1832
1833			run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()));
1834			assert_eq!(
1835				RelayersPallet::<TestRuntime>::relayer_reward(
1836					relayer_account_at_this_chain(),
1837					MsgProofsRewardsAccount::get()
1838				),
1839				Some(expected_delivery_reward()),
1840			);
1841
1842			run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(()));
1843			assert_eq!(
1844				RelayersPallet::<TestRuntime>::relayer_reward(
1845					relayer_account_at_this_chain(),
1846					MsgDeliveryProofsRewardsAccount::get()
1847				),
1848				Some(expected_confirmation_reward()),
1849			);
1850		});
1851	}
1852
1853	#[test]
1854	fn post_dispatch_refunds_relayer_in_parachain_finality_batch() {
1855		run_test(|| {
1856			initialize_environment(200, 200, 200);
1857
1858			run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(()));
1859			assert_eq!(
1860				RelayersPallet::<TestRuntime>::relayer_reward(
1861					relayer_account_at_this_chain(),
1862					MsgProofsRewardsAccount::get()
1863				),
1864				Some(expected_delivery_reward()),
1865			);
1866
1867			run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(()));
1868			assert_eq!(
1869				RelayersPallet::<TestRuntime>::relayer_reward(
1870					relayer_account_at_this_chain(),
1871					MsgDeliveryProofsRewardsAccount::get()
1872				),
1873				Some(expected_confirmation_reward()),
1874			);
1875		});
1876	}
1877
1878	#[test]
1879	fn post_dispatch_refunds_relayer_in_message_transaction() {
1880		run_test(|| {
1881			initialize_environment(200, 200, 200);
1882
1883			run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()));
1884			assert_eq!(
1885				RelayersPallet::<TestRuntime>::relayer_reward(
1886					relayer_account_at_this_chain(),
1887					MsgProofsRewardsAccount::get()
1888				),
1889				Some(expected_delivery_reward()),
1890			);
1891
1892			run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()));
1893			assert_eq!(
1894				RelayersPallet::<TestRuntime>::relayer_reward(
1895					relayer_account_at_this_chain(),
1896					MsgDeliveryProofsRewardsAccount::get()
1897				),
1898				Some(expected_confirmation_reward()),
1899			);
1900		});
1901	}
1902
1903	#[test]
1904	fn post_dispatch_slashing_relayer_stake() {
1905		run_test(|| {
1906			initialize_environment(200, 200, 100);
1907
1908			let delivery_rewards_account_balance =
1909				Balances::free_balance(delivery_rewards_account());
1910
1911			let test_stake: ThisChainBalance = Stake::get();
1912			Balances::set_balance(
1913				&relayer_account_at_this_chain(),
1914				ExistentialDeposit::get() + test_stake * 10,
1915			);
1916
1917			// slashing works for message delivery calls
1918			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1919				.unwrap();
1920			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1921			run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()));
1922			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0);
1923			assert_eq!(
1924				delivery_rewards_account_balance + test_stake,
1925				Balances::free_balance(delivery_rewards_account())
1926			);
1927
1928			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1929				.unwrap();
1930			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1931			run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(()));
1932			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0);
1933			assert_eq!(
1934				delivery_rewards_account_balance + test_stake * 2,
1935				Balances::free_balance(delivery_rewards_account())
1936			);
1937
1938			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
1939				.unwrap();
1940			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1941			run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()));
1942			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0);
1943			assert_eq!(
1944				delivery_rewards_account_balance + test_stake * 3,
1945				Balances::free_balance(delivery_rewards_account())
1946			);
1947
1948			// reserve doesn't work for message confirmation calls
1949			let confirmation_rewards_account_balance =
1950				Balances::free_balance(confirmation_rewards_account());
1951
1952			Balances::reserve(&relayer_account_at_this_chain(), test_stake).unwrap();
1953			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1954
1955			assert_eq!(
1956				confirmation_rewards_account_balance,
1957				Balances::free_balance(confirmation_rewards_account())
1958			);
1959			run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()));
1960			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1961
1962			run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(()));
1963			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1964
1965			run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(()));
1966			assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake);
1967
1968			// check that unreserve has happened, not slashing
1969			assert_eq!(
1970				delivery_rewards_account_balance + test_stake * 3,
1971				Balances::free_balance(delivery_rewards_account())
1972			);
1973			assert_eq!(
1974				confirmation_rewards_account_balance,
1975				Balances::free_balance(confirmation_rewards_account())
1976			);
1977		});
1978	}
1979
1980	fn run_analyze_call_result(
1981		pre_dispatch_data: PreDispatchData<
1982			ThisChainAccountId,
1983			BridgedChainBlockNumber,
1984			TestLaneIdType,
1985		>,
1986		dispatch_result: DispatchResult,
1987	) -> RelayerAccountAction<ThisChainAccountId, RewardBalance, TestLaneIdType> {
1988		TestExtension::analyze_call_result(
1989			Some(pre_dispatch_data),
1990			&dispatch_info(),
1991			&post_dispatch_info(),
1992			1024,
1993			&dispatch_result,
1994		)
1995	}
1996
1997	#[test]
1998	fn analyze_call_result_shall_not_slash_for_transactions_with_too_many_messages() {
1999		run_test(|| {
2000			initialize_environment(100, 100, 100);
2001
2002			// the `analyze_call_result` should return slash if number of bundled messages is
2003			// within reasonable limits
2004			assert_eq!(
2005				run_analyze_call_result(all_finality_pre_dispatch_data(), Ok(())),
2006				RelayerAccountAction::Slash(
2007					relayer_account_at_this_chain(),
2008					MsgProofsRewardsAccount::get()
2009				),
2010			);
2011			assert_eq!(
2012				run_analyze_call_result(parachain_finality_pre_dispatch_data(), Ok(())),
2013				RelayerAccountAction::Slash(
2014					relayer_account_at_this_chain(),
2015					MsgProofsRewardsAccount::get()
2016				),
2017			);
2018			assert_eq!(
2019				run_analyze_call_result(delivery_pre_dispatch_data(), Ok(())),
2020				RelayerAccountAction::Slash(
2021					relayer_account_at_this_chain(),
2022					MsgProofsRewardsAccount::get()
2023				),
2024			);
2025
2026			// the `analyze_call_result` should not return slash if number of bundled messages is
2027			// larger than the
2028			assert_eq!(
2029				run_analyze_call_result(
2030					set_bundled_range_end(all_finality_pre_dispatch_data(), 1_000_000),
2031					Ok(())
2032				),
2033				RelayerAccountAction::None,
2034			);
2035			assert_eq!(
2036				run_analyze_call_result(
2037					set_bundled_range_end(parachain_finality_pre_dispatch_data(), 1_000_000),
2038					Ok(())
2039				),
2040				RelayerAccountAction::None,
2041			);
2042			assert_eq!(
2043				run_analyze_call_result(
2044					set_bundled_range_end(delivery_pre_dispatch_data(), 1_000_000),
2045					Ok(())
2046				),
2047				RelayerAccountAction::None,
2048			);
2049		});
2050	}
2051
2052	#[test]
2053	fn grandpa_ext_only_parses_valid_batches() {
2054		run_test(|| {
2055			initialize_environment(100, 100, 100);
2056
2057			// relay + parachain + message delivery calls batch is ignored
2058			assert_eq!(
2059				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2060					&all_finality_and_delivery_batch_call(200, 200, 200)
2061				),
2062				Ok(None),
2063			);
2064
2065			// relay + parachain + message confirmation calls batch is ignored
2066			assert_eq!(
2067				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2068					&all_finality_and_confirmation_batch_call(200, 200, 200)
2069				),
2070				Ok(None),
2071			);
2072
2073			// parachain + message delivery call batch is ignored
2074			assert_eq!(
2075				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2076					&parachain_finality_and_delivery_batch_call(200, 200)
2077				),
2078				Ok(None),
2079			);
2080
2081			// parachain + message confirmation call batch is ignored
2082			assert_eq!(
2083				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2084					&parachain_finality_and_confirmation_batch_call(200, 200)
2085				),
2086				Ok(None),
2087			);
2088
2089			// relay + message delivery call batch is accepted
2090			assert_eq!(
2091				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2092					&relay_finality_and_delivery_batch_call(200, 200)
2093				),
2094				Ok(Some(relay_finality_pre_dispatch_data().call_info)),
2095			);
2096
2097			// relay + message confirmation call batch is accepted
2098			assert_eq!(
2099				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2100					&relay_finality_and_confirmation_batch_call(200, 200)
2101				),
2102				Ok(Some(relay_finality_confirmation_pre_dispatch_data().call_info)),
2103			);
2104
2105			// message delivery call batch is accepted
2106			assert_eq!(
2107				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2108					&message_delivery_call(200)
2109				),
2110				Ok(Some(delivery_pre_dispatch_data().call_info)),
2111			);
2112
2113			// message confirmation call batch is accepted
2114			assert_eq!(
2115				TestGrandpaExtensionConfig::parse_and_check_for_obsolete_call(
2116					&message_confirmation_call(200)
2117				),
2118				Ok(Some(confirmation_pre_dispatch_data().call_info)),
2119			);
2120		});
2121	}
2122
2123	#[test]
2124	fn messages_ext_only_parses_standalone_transactions() {
2125		run_test(|| {
2126			initialize_environment(100, 100, 100);
2127
2128			// relay + parachain + message delivery calls batch is ignored
2129			assert_eq!(
2130				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2131					&all_finality_and_delivery_batch_call(200, 200, 200)
2132				),
2133				Ok(None),
2134			);
2135			assert_eq!(
2136				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2137					&all_finality_and_delivery_batch_call_ex(200, 200, 200)
2138				),
2139				Ok(None),
2140			);
2141
2142			// relay + parachain + message confirmation calls batch is ignored
2143			assert_eq!(
2144				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2145					&all_finality_and_confirmation_batch_call(200, 200, 200)
2146				),
2147				Ok(None),
2148			);
2149			assert_eq!(
2150				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2151					&all_finality_and_confirmation_batch_call_ex(200, 200, 200)
2152				),
2153				Ok(None),
2154			);
2155
2156			// parachain + message delivery call batch is ignored
2157			assert_eq!(
2158				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2159					&parachain_finality_and_delivery_batch_call(200, 200)
2160				),
2161				Ok(None),
2162			);
2163
2164			// parachain + message confirmation call batch is ignored
2165			assert_eq!(
2166				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2167					&parachain_finality_and_confirmation_batch_call(200, 200)
2168				),
2169				Ok(None),
2170			);
2171
2172			// relay + message delivery call batch is ignored
2173			assert_eq!(
2174				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2175					&relay_finality_and_delivery_batch_call(200, 200)
2176				),
2177				Ok(None),
2178			);
2179			assert_eq!(
2180				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2181					&relay_finality_and_delivery_batch_call_ex(200, 200)
2182				),
2183				Ok(None),
2184			);
2185
2186			// relay + message confirmation call batch is ignored
2187			assert_eq!(
2188				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2189					&relay_finality_and_confirmation_batch_call(200, 200)
2190				),
2191				Ok(None),
2192			);
2193			assert_eq!(
2194				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2195					&relay_finality_and_confirmation_batch_call_ex(200, 200)
2196				),
2197				Ok(None),
2198			);
2199
2200			// message delivery call batch is accepted
2201			assert_eq!(
2202				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2203					&message_delivery_call(200)
2204				),
2205				Ok(Some(delivery_pre_dispatch_data().call_info)),
2206			);
2207
2208			// message confirmation call batch is accepted
2209			assert_eq!(
2210				TestMessagesExtensionConfig::parse_and_check_for_obsolete_call(
2211					&message_confirmation_call(200)
2212				),
2213				Ok(Some(confirmation_pre_dispatch_data().call_info)),
2214			);
2215		});
2216	}
2217
2218	#[test]
2219	fn messages_ext_rejects_calls_with_obsolete_messages() {
2220		run_test(|| {
2221			initialize_environment(100, 100, 100);
2222
2223			assert_eq!(
2224				run_messages_pre_dispatch(message_delivery_call(100)),
2225				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2226			);
2227			assert_eq!(
2228				run_messages_pre_dispatch(message_confirmation_call(100)),
2229				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2230			);
2231
2232			assert_eq!(
2233				run_messages_validate(message_delivery_call(100)),
2234				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2235			);
2236			assert_eq!(
2237				run_messages_validate(message_confirmation_call(100)),
2238				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2239			);
2240		});
2241	}
2242
2243	#[test]
2244	fn messages_ext_accepts_calls_with_new_messages() {
2245		run_test(|| {
2246			initialize_environment(100, 100, 100);
2247
2248			assert_eq!(
2249				run_messages_pre_dispatch(message_delivery_call(200)),
2250				Ok(Some(delivery_pre_dispatch_data())),
2251			);
2252			assert_eq!(
2253				run_messages_pre_dispatch(message_confirmation_call(200)),
2254				Ok(Some(confirmation_pre_dispatch_data())),
2255			);
2256
2257			assert_eq!(run_messages_validate(message_delivery_call(200)), Ok(Default::default()),);
2258			assert_eq!(
2259				run_messages_validate(message_confirmation_call(200)),
2260				Ok(Default::default()),
2261			);
2262		});
2263	}
2264
2265	#[test]
2266	fn grandpa_ext_rejects_batch_with_obsolete_relay_chain_header() {
2267		run_test(|| {
2268			initialize_environment(100, 100, 100);
2269
2270			assert_eq!(
2271				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(100, 200)),
2272				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2273			);
2274			assert_eq!(
2275				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(100, 200)),
2276				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2277			);
2278
2279			assert_eq!(
2280				run_grandpa_validate(relay_finality_and_delivery_batch_call(100, 200)),
2281				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2282			);
2283			assert_eq!(
2284				run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(100, 200)),
2285				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2286			);
2287		});
2288	}
2289
2290	#[test]
2291	fn grandpa_ext_rejects_calls_with_obsolete_messages() {
2292		run_test(|| {
2293			initialize_environment(100, 100, 100);
2294
2295			assert_eq!(
2296				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 100)),
2297				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2298			);
2299			assert_eq!(
2300				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(200, 100)),
2301				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2302			);
2303			assert_eq!(
2304				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 100)),
2305				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2306			);
2307			assert_eq!(
2308				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call_ex(200, 100)),
2309				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2310			);
2311
2312			assert_eq!(
2313				run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 100)),
2314				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2315			);
2316			assert_eq!(
2317				run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(200, 100)),
2318				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2319			);
2320			assert_eq!(
2321				run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 100)),
2322				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2323			);
2324			assert_eq!(
2325				run_grandpa_validate(relay_finality_and_confirmation_batch_call_ex(200, 100)),
2326				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2327			);
2328
2329			assert_eq!(
2330				run_grandpa_pre_dispatch(message_delivery_call(100)),
2331				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2332			);
2333			assert_eq!(
2334				run_grandpa_pre_dispatch(message_confirmation_call(100)),
2335				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2336			);
2337
2338			assert_eq!(
2339				run_grandpa_validate(message_delivery_call(100)),
2340				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2341			);
2342			assert_eq!(
2343				run_grandpa_validate(message_confirmation_call(100)),
2344				Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)),
2345			);
2346		});
2347	}
2348
2349	#[test]
2350	fn grandpa_ext_accepts_calls_with_new_messages() {
2351		run_test(|| {
2352			initialize_environment(100, 100, 100);
2353
2354			assert_eq!(
2355				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 200)),
2356				Ok(Some(relay_finality_pre_dispatch_data()),)
2357			);
2358			assert_eq!(
2359				run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(200, 200)),
2360				Ok(Some(relay_finality_pre_dispatch_data_ex()),)
2361			);
2362			assert_eq!(
2363				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 200)),
2364				Ok(Some(relay_finality_confirmation_pre_dispatch_data())),
2365			);
2366			assert_eq!(
2367				run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call_ex(200, 200)),
2368				Ok(Some(relay_finality_confirmation_pre_dispatch_data_ex())),
2369			);
2370
2371			assert_eq!(
2372				run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 200)),
2373				Ok(Default::default()),
2374			);
2375			assert_eq!(
2376				run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(200, 200)),
2377				Ok(Default::default()),
2378			);
2379			assert_eq!(
2380				run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 200)),
2381				Ok(Default::default()),
2382			);
2383			assert_eq!(
2384				run_grandpa_validate(relay_finality_and_confirmation_batch_call_ex(200, 200)),
2385				Ok(Default::default()),
2386			);
2387
2388			assert_eq!(
2389				run_grandpa_pre_dispatch(message_delivery_call(200)),
2390				Ok(Some(delivery_pre_dispatch_data())),
2391			);
2392			assert_eq!(
2393				run_grandpa_pre_dispatch(message_confirmation_call(200)),
2394				Ok(Some(confirmation_pre_dispatch_data())),
2395			);
2396
2397			assert_eq!(run_grandpa_validate(message_delivery_call(200)), Ok(Default::default()),);
2398			assert_eq!(
2399				run_grandpa_validate(message_confirmation_call(200)),
2400				Ok(Default::default()),
2401			);
2402		});
2403	}
2404
2405	#[test]
2406	fn does_not_panic_on_boosting_priority_of_empty_message_delivery_transaction() {
2407		run_test(|| {
2408			let best_delivered_message =
2409				BridgedUnderlyingParachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
2410			initialize_environment(100, 100, best_delivered_message);
2411
2412			// register relayer so it gets priority boost
2413			BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000)
2414				.unwrap();
2415
2416			// allow empty message delivery transactions
2417			let lane_id = test_lane_id();
2418			let in_lane_data = InboundLaneData {
2419				last_confirmed_nonce: 0,
2420				relayers: vec![UnrewardedRelayer {
2421					relayer: relayer_account_at_bridged_chain(),
2422					messages: DeliveredMessages { begin: 1, end: best_delivered_message },
2423				}]
2424				.into(),
2425				..Default::default()
2426			};
2427			pallet_bridge_messages::InboundLanes::<TestRuntime>::insert(lane_id, in_lane_data);
2428
2429			// now check that the priority of empty tx is the same as priority of 1-message tx
2430			let priority_of_zero_messages_delivery =
2431				run_validate(message_delivery_call(best_delivered_message)).unwrap().priority;
2432			let priority_of_one_messages_delivery =
2433				run_validate(message_delivery_call(best_delivered_message + 1))
2434					.unwrap()
2435					.priority;
2436
2437			assert_eq!(priority_of_zero_messages_delivery, priority_of_one_messages_delivery);
2438		});
2439	}
2440}