1
// Copyright 2019-2021 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
#![cfg(test)]
18

            
19
use crate as pallet_xcm_bridge;
20
use bp_messages::{
21
	target_chain::{DispatchMessage, MessageDispatch},
22
	ChainWithMessages, HashedLaneId, MessageNonce,
23
};
24
use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, HashOf};
25
use bp_xcm_bridge::{BridgeId, BridgeLocations, LocalXcmChannelManager};
26
use frame_support::{
27
	assert_ok, derive_impl, parameter_types,
28
	traits::{fungible::Mutate, EitherOf, EnsureOrigin, Equals, Everything, Get, OriginTrait},
29
	weights::RuntimeDbWeight,
30
};
31
use frame_system::{EnsureNever, EnsureRoot, EnsureRootWithSuccess};
32
use pallet_xcm_bridge::congestion::{
33
	BlobDispatcherWithChannelStatus, CongestionLimits, HereOrLocalConsensusXcmChannelManager,
34
	UpdateBridgeStatusXcmChannelManager,
35
};
36
use parity_scale_codec::{Decode, Encode};
37
use polkadot_parachain::primitives::Sibling;
38
use sp_core::H256;
39
use sp_runtime::{
40
	testing::Header as SubstrateHeader,
41
	traits::{BlakeTwo256, ConstU32, Convert, IdentityLookup},
42
	AccountId32, BuildStorage, StateVersion,
43
};
44
use sp_std::{cell::RefCell, marker::PhantomData};
45
use xcm::latest::SendError::{MissingArgument, NotApplicable};
46
use xcm::prelude::*;
47
use xcm_builder::{
48
	ensure_is_remote, AllowUnpaidExecutionFrom, DispatchBlob, DispatchBlobError, FixedWeightBounds,
49
	InspectMessageQueues, NetworkExportTable, NetworkExportTableItem, ParentIsPreset,
50
	SiblingParachainConvertsVia, SovereignPaidRemoteExporter,
51
};
52
use xcm_executor::traits::{validate_export, ExportXcm};
53
use xcm_executor::{
54
	traits::{ConvertLocation, ConvertOrigin},
55
	XcmExecutor,
56
};
57

            
58
pub type AccountId = AccountId32;
59
pub type Balance = u64;
60
type Block = frame_system::mocking::MockBlock<TestRuntime>;
61

            
62
/// Lane identifier type used for tests.
63
pub type TestLaneIdType = HashedLaneId;
64

            
65
pub const SIBLING_ASSET_HUB_ID: u32 = 2001;
66
pub const THIS_BRIDGE_HUB_ID: u32 = 2002;
67
pub const BRIDGED_ASSET_HUB_ID: u32 = 1001;
68

            
69
919630
frame_support::construct_runtime! {
70
	pub enum TestRuntime {
71
		System: frame_system,
72
		Balances: pallet_balances,
73
		Messages: pallet_bridge_messages,
74
		XcmOverBridge: pallet_xcm_bridge,
75
		XcmOverBridgeWrappedWithExportMessageRouter: pallet_xcm_bridge_router = 57,
76
		XcmOverBridgeByExportXcmRouter: pallet_xcm_bridge_router::<Instance2> = 69,
77
	}
78
2790302
}
79

            
80
parameter_types! {
81
	pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 };
82
	pub const ExistentialDeposit: Balance = 1;
83
}
84

            
85
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
86
impl frame_system::Config for TestRuntime {
87
	type AccountId = AccountId;
88
	type AccountData = pallet_balances::AccountData<Balance>;
89
	type Block = Block;
90
	type Lookup = IdentityLookup<Self::AccountId>;
91
}
92

            
93
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
94
impl pallet_balances::Config for TestRuntime {
95
	type AccountStore = System;
96
}
97

            
98
impl pallet_bridge_messages::Config for TestRuntime {
99
	type RuntimeEvent = RuntimeEvent;
100
	type WeightInfo = TestMessagesWeights;
101

            
102
	type ThisChain = ThisUnderlyingChain;
103
	type BridgedChain = BridgedUnderlyingChain;
104
	type BridgedHeaderChain = BridgedHeaderChain;
105

            
106
	type OutboundPayload = Vec<u8>;
107
	type InboundPayload = Vec<u8>;
108
	type LaneId = TestLaneIdType;
109

            
110
	type DeliveryPayments = ();
111
	type DeliveryConfirmationPayments = ();
112
	type OnMessagesDelivered = ();
113

            
114
	type MessageDispatch = TestMessageDispatch;
115
}
116

            
117
pub struct TestMessagesWeights;
118

            
119
impl pallet_bridge_messages::WeightInfo for TestMessagesWeights {
120
	fn receive_single_message_proof() -> Weight {
121
		Weight::zero()
122
	}
123
	fn receive_n_messages_proof(_: u32) -> Weight {
124
		Weight::zero()
125
	}
126
	fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
127
		Weight::zero()
128
	}
129
1
	fn receive_single_n_bytes_message_proof(_: u32) -> Weight {
130
1
		Weight::zero()
131
1
	}
132
	fn receive_delivery_proof_for_single_message() -> Weight {
133
		Weight::zero()
134
	}
135
	fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
136
		Weight::zero()
137
	}
138
	fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
139
		Weight::zero()
140
	}
141
1
	fn receive_single_n_bytes_message_proof_with_dispatch(_n: u32) -> Weight {
142
1
		Weight::from_parts(1, 0)
143
1
	}
144
}
145

            
146
impl pallet_bridge_messages::WeightInfoExt for TestMessagesWeights {
147
	fn expected_extra_storage_proof_size() -> u32 {
148
		0
149
	}
150

            
151
	fn receive_messages_proof_overhead_from_runtime() -> Weight {
152
		Weight::zero()
153
	}
154

            
155
	fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
156
		Weight::zero()
157
	}
158
}
159

            
160
parameter_types! {
161
	pub const HereLocation: Location = Location::here();
162
	pub const RelayNetwork: NetworkId = NetworkId::Kusama;
163
	pub UniversalLocation: InteriorLocation = [
164
		GlobalConsensus(RelayNetwork::get()),
165
		Parachain(THIS_BRIDGE_HUB_ID),
166
	].into();
167
	pub SiblingLocation: Location = Location::new(1, [Parachain(SIBLING_ASSET_HUB_ID)]);
168
	pub SiblingUniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(SIBLING_ASSET_HUB_ID)].into();
169

            
170
	pub const BridgedRelayNetwork: NetworkId = NetworkId::ByGenesis([1; 32]);
171
	pub BridgedRelayNetworkLocation: Location = (Parent, GlobalConsensus(BridgedRelayNetwork::get())).into();
172
	pub BridgedRelativeDestination: InteriorLocation = [Parachain(BRIDGED_ASSET_HUB_ID)].into();
173
	pub BridgedUniversalDestination: InteriorLocation = [GlobalConsensus(BridgedRelayNetwork::get()), Parachain(BRIDGED_ASSET_HUB_ID)].into();
174
	pub const NonBridgedRelayNetwork: NetworkId = NetworkId::Rococo;
175

            
176
	pub const BridgeDeposit: Balance = 100_000;
177

            
178
	// configuration for pallet_xcm_bridge_hub_router
179
	pub BridgeHubLocation: Location = Here.into();
180
	pub BridgeTable: Vec<NetworkExportTableItem>
181
		= vec![
182
			NetworkExportTableItem::new(
183
				BridgedRelayNetwork::get(),
184
				None,
185
				BridgeHubLocation::get(),
186
				None
187
			)
188
		];
189
	pub UnitWeightCost: Weight = Weight::from_parts(10, 10);
190
57389
	pub storage TestCongestionLimits: CongestionLimits = CongestionLimits::default();
191
}
192

            
193
/// Implementation of `SendXcm` which uses the given `ExportXcm` implementation in order to forward
194
/// the message over a bridge.
195
///
196
/// This is only useful when the local chain has bridging capabilities.
197
pub struct LocalExporter<Exporter, UniversalLocation>(PhantomData<(Exporter, UniversalLocation)>);
198
impl<Exporter: ExportXcm, UniversalLocation: Get<InteriorLocation>> SendXcm
199
	for LocalExporter<Exporter, UniversalLocation>
200
{
201
	type Ticket = Exporter::Ticket;
202

            
203
8194
	fn validate(
204
8194
		dest: &mut Option<Location>,
205
8194
		msg: &mut Option<Xcm<()>>,
206
8194
	) -> SendResult<Exporter::Ticket> {
207
		// This `clone` ensures that `dest` is not consumed in any case.
208
8194
		let d = dest.clone().ok_or(MissingArgument)?;
209
8194
		let universal_source = UniversalLocation::get();
210
8194
		let devolved = ensure_is_remote(universal_source.clone(), d).map_err(|_| NotApplicable)?;
211
8194
		let (remote_network, remote_location) = devolved;
212
8194
		let xcm = msg.take().ok_or(MissingArgument)?;
213

            
214
8194
		let hash =
215
8194
			(Some(Location::here()), &remote_location).using_encoded(sp_io::hashing::blake2_128);
216
8194
		let channel = u32::decode(&mut hash.as_ref()).unwrap_or(0);
217
8194

            
218
8194
		validate_export::<Exporter>(
219
8194
			remote_network,
220
8194
			channel,
221
8194
			universal_source,
222
8194
			remote_location,
223
8194
			xcm.clone(),
224
8194
		)
225
8194
		.inspect_err(|err| {
226
			if let NotApplicable = err {
227
				// We need to make sure that msg is not consumed in case of `NotApplicable`.
228
				*msg = Some(xcm);
229
			}
230
8194
		})
231
8194
	}
232

            
233
8194
	fn deliver(ticket: Exporter::Ticket) -> Result<XcmHash, SendError> {
234
8194
		Exporter::deliver(ticket)
235
8194
	}
236
}
237

            
238
/// **Universal** `InteriorLocation` of bridged asset hub.
239
32806
pub fn bridged_asset_hub_universal_location() -> InteriorLocation {
240
32806
	BridgedUniversalDestination::get()
241
32806
}
242

            
243
pub(crate) type TestLocalXcmChannelManager = TestingLocalXcmChannelManager<
244
	BridgeId,
245
	HereOrLocalConsensusXcmChannelManager<
246
		BridgeId,
247
		// handles congestion for `XcmOverBridgeByExportXcmRouter`
248
		XcmOverBridgeByExportXcmRouter,
249
		// handles congestion for `XcmOverBridgeWrappedWithExportMessageRouter`
250
		UpdateBridgeStatusXcmChannelManager<
251
			TestRuntime,
252
			(),
253
			UpdateBridgeStatusXcmProvider,
254
			FromBridgeHubLocationXcmSender<ExecuteXcmOverSendXcm>,
255
		>,
256
	>,
257
>;
258

            
259
impl pallet_xcm_bridge::Config for TestRuntime {
260
	type RuntimeEvent = RuntimeEvent;
261
	type WeightInfo = ();
262

            
263
	type UniversalLocation = UniversalLocation;
264
	type BridgedNetwork = BridgedRelayNetworkLocation;
265
	type BridgeMessagesPalletInstance = ();
266

            
267
	type MessageExportPrice = ();
268
	type DestinationVersion = AlwaysLatest;
269

            
270
	type ForceOrigin = EnsureNever<()>;
271
	type OpenBridgeOrigin = EitherOf<
272
		// We want to translate `RuntimeOrigin::root()` to the `Location::here()`
273
		EnsureRootWithSuccess<AccountId, HereLocation>,
274
		OpenBridgeOrigin,
275
	>;
276
	type BridgeOriginAccountIdConverter = LocationToAccountId;
277

            
278
	type BridgeDeposit = BridgeDeposit;
279
	type Currency = Balances;
280
	type RuntimeHoldReason = RuntimeHoldReason;
281
	type AllowWithoutBridgeDeposit = (Equals<ParentRelayChainLocation>, Equals<HereLocation>);
282

            
283
	type LocalXcmChannelManager = TestLocalXcmChannelManager;
284
	type BlobDispatcher = BlobDispatcherWithChannelStatus<TestBlobDispatcher, TestBlobDispatcher>;
285
	type CongestionLimits = TestCongestionLimits;
286
}
287

            
288
#[cfg(feature = "runtime-benchmarks")]
289
impl crate::benchmarking::Config<()> for TestRuntime {
290
	fn open_bridge_origin() -> Option<(RuntimeOrigin, Balance)> {
291
		Some((
292
			OpenBridgeOrigin::sibling_parachain_origin(),
293
			ExistentialDeposit::get(),
294
		))
295
	}
296
}
297

            
298
/// A router instance simulates a scenario where the router is deployed on a different chain than
299
/// the `MessageExporter`. This means that the router sends an `ExportMessage`.
300
pub type XcmOverBridgeWrappedWithExportMessageRouterInstance = ();
301
#[derive_impl(pallet_xcm_bridge_router::config_preludes::TestDefaultConfig)]
302
impl pallet_xcm_bridge_router::Config<XcmOverBridgeWrappedWithExportMessageRouterInstance>
303
	for TestRuntime
304
{
305
	// We use `SovereignPaidRemoteExporter` here to test and ensure that the `ExportMessage`
306
	// produced by `pallet_xcm_bridge_hub_router` is compatible with the `ExportXcm` implementation
307
	// of `pallet_xcm_bridge_hub`.
308
	type MessageExporter = SovereignPaidRemoteExporter<
309
		pallet_xcm_bridge_router::impls::ViaRemoteBridgeExporter<
310
			TestRuntime,
311
			// () - means `pallet_xcm_bridge_router::Config<()>`
312
			(),
313
			NetworkExportTable<BridgeTable>,
314
			BridgedRelayNetwork,
315
			BridgeHubLocation,
316
		>,
317
		// **Note**: The crucial part is that `ExportMessage` is processed by `XcmExecutor`, which
318
		// calls the `ExportXcm` implementation of `pallet_xcm_bridge_hub` as the
319
		// `MessageExporter`.
320
		ExecuteXcmOverSendXcm,
321
		ExportMessageOriginUniversalLocation,
322
	>;
323

            
324
	type BridgeIdResolver = pallet_xcm_bridge_router::impls::EnsureIsRemoteBridgeIdResolver<
325
		ExportMessageOriginUniversalLocation,
326
	>;
327
	// We convert to root here `BridgeHubLocationXcmOriginAsRoot`
328
	type UpdateBridgeStatusOrigin = EnsureRoot<AccountId>;
329
}
330

            
331
/// A router instance simulates a scenario where the router is deployed on the same chain as the
332
/// `MessageExporter`. This means that the router triggers `ExportXcm` trait directly.
333
pub type XcmOverBridgeByExportXcmRouterInstance = pallet_xcm_bridge_router::Instance2;
334
#[derive_impl(pallet_xcm_bridge_router::config_preludes::TestDefaultConfig)]
335
impl pallet_xcm_bridge_router::Config<XcmOverBridgeByExportXcmRouterInstance> for TestRuntime {
336
	// We use `LocalExporter` with `ViaLocalBridgeExporter` here to test and ensure that
337
	// `pallet_xcm_bridge_hub_router` can trigger directly `pallet_xcm_bridge_hub` as exporter.
338
	type MessageExporter = pallet_xcm_bridge_router::impls::ViaLocalBridgeExporter<
339
		TestRuntime,
340
		XcmOverBridgeByExportXcmRouterInstance,
341
		LocalExporter<XcmOverBridge, UniversalLocation>,
342
	>;
343

            
344
	type BridgeIdResolver =
345
		pallet_xcm_bridge_router::impls::EnsureIsRemoteBridgeIdResolver<UniversalLocation>;
346
	// We don't need to support here `update_bridge_status`.
347
	type UpdateBridgeStatusOrigin = EnsureNever<()>;
348
}
349

            
350
/// A dynamic way to set different universal location for the origin which sends `ExportMessage`.
351
pub struct ExportMessageOriginUniversalLocation;
352
impl ExportMessageOriginUniversalLocation {
353
3
	pub(crate) fn set(universal_location: Option<InteriorLocation>) {
354
3
		EXPORT_MESSAGE_ORIGIN_UNIVERSAL_LOCATION.with(|o| *o.borrow_mut() = universal_location);
355
3
	}
356
}
357
impl Get<InteriorLocation> for ExportMessageOriginUniversalLocation {
358
57370
	fn get() -> InteriorLocation {
359
57370
		EXPORT_MESSAGE_ORIGIN_UNIVERSAL_LOCATION.with(|o| {
360
57370
			o.borrow()
361
57370
				.clone()
362
57370
				.expect("`EXPORT_MESSAGE_ORIGIN_UNIVERSAL_LOCATION` is not set!")
363
57370
		})
364
57370
	}
365
}
366
2
thread_local! {
367
2
	pub static EXPORT_MESSAGE_ORIGIN_UNIVERSAL_LOCATION: RefCell<Option<InteriorLocation>> = RefCell::new(None);
368
2
}
369

            
370
pub struct BridgeHubLocationXcmOriginAsRoot<RuntimeOrigin>(PhantomData<RuntimeOrigin>);
371
impl<RuntimeOrigin: OriginTrait> ConvertOrigin<RuntimeOrigin>
372
	for BridgeHubLocationXcmOriginAsRoot<RuntimeOrigin>
373
{
374
2
	fn convert_origin(
375
2
		origin: impl Into<Location>,
376
2
		kind: OriginKind,
377
2
	) -> Result<RuntimeOrigin, Location> {
378
2
		let origin = origin.into();
379
2
		if kind == OriginKind::Xcm && origin.eq(&BridgeHubLocation::get()) {
380
2
			Ok(RuntimeOrigin::root())
381
		} else {
382
			Err(origin)
383
		}
384
2
	}
385
}
386

            
387
pub struct XcmConfig;
388
impl xcm_executor::Config for XcmConfig {
389
	type RuntimeCall = RuntimeCall;
390
	type XcmSender = ();
391
	type AssetTransactor = ();
392
	type OriginConverter = BridgeHubLocationXcmOriginAsRoot<RuntimeOrigin>;
393
	type IsReserve = ();
394
	type IsTeleporter = ();
395
	type UniversalLocation = UniversalLocation;
396
	type Barrier = AllowUnpaidExecutionFrom<Everything>;
397
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, ConstU32<100>>;
398
	type Trader = ();
399
	type ResponseHandler = ();
400
	type AssetTrap = ();
401
	type AssetClaims = ();
402
	type SubscriptionService = ();
403
	type PalletInstancesInfo = ();
404
	type MaxAssetsIntoHolding = ();
405
	type AssetLocker = ();
406
	type AssetExchanger = ();
407
	type FeeManager = ();
408
	// We just set `MessageExporter` as our `pallet_xcm_bridge_hub` instance.
409
	type MessageExporter = (XcmOverBridge,);
410
	type UniversalAliases = ();
411
	type CallDispatcher = RuntimeCall;
412
	type SafeCallFilter = Everything;
413
	type Aliasers = ();
414
	type TransactionalProcessor = ();
415
	type HrmpNewChannelOpenRequestHandler = ();
416
	type HrmpChannelAcceptedHandler = ();
417
	type HrmpChannelClosingHandler = ();
418
	type XcmRecorder = ();
419
}
420

            
421
2
thread_local! {
422
2
	pub static EXECUTE_XCM_ORIGIN: RefCell<Option<Location>> = RefCell::new(None);
423
2
}
424

            
425
/// The `SendXcm` implementation directly executes XCM using `XcmExecutor`.
426
pub struct ExecuteXcmOverSendXcm;
427
impl SendXcm for ExecuteXcmOverSendXcm {
428
	type Ticket = Xcm<()>;
429

            
430
8197
	fn validate(
431
8197
		_: &mut Option<Location>,
432
8197
		message: &mut Option<Xcm<()>>,
433
8197
	) -> SendResult<Self::Ticket> {
434
8197
		Ok((message.take().unwrap(), Assets::new()))
435
8197
	}
436

            
437
8197
	fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
438
8197
		let xcm: Xcm<RuntimeCall> = ticket.into();
439
8197

            
440
8197
		let origin = EXECUTE_XCM_ORIGIN.with(|o| o.borrow().clone().unwrap());
441
8197
		let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
442
8197
		let outcome = XcmExecutor::<XcmConfig>::prepare_and_execute(
443
8197
			origin,
444
8197
			xcm,
445
8197
			&mut hash,
446
8197
			Weight::MAX,
447
8197
			Weight::zero(),
448
8197
		);
449
8197
		assert_ok!(outcome.ensure_complete());
450

            
451
8197
		Ok(hash)
452
8197
	}
453
}
454
impl InspectMessageQueues for ExecuteXcmOverSendXcm {
455
	fn clear_messages() {
456
		todo!()
457
	}
458

            
459
	fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)> {
460
		todo!()
461
	}
462
}
463
impl ExecuteXcmOverSendXcm {
464
8197
	pub fn set_origin_for_execute(origin: Location) {
465
8197
		EXECUTE_XCM_ORIGIN.with(|o| *o.borrow_mut() = Some(origin));
466
8197
	}
467
}
468

            
469
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
470
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
471
/// `Transact` in order to determine the dispatch Origin.
472
pub type LocationToAccountId = (
473
	// The parent (Relay-chain) origin converts to the parent `AccountId`.
474
	ParentIsPreset<AccountId>,
475
	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
476
	SiblingParachainConvertsVia<Sibling, AccountId>,
477
);
478

            
479
parameter_types! {
480
	pub ParentRelayChainLocation: Location = Location { parents: 1, interior: Here };
481
}
482
pub struct OpenBridgeOrigin;
483

            
484
impl OpenBridgeOrigin {
485
32826
	pub fn parent_relay_chain_origin() -> RuntimeOrigin {
486
32826
		RuntimeOrigin::signed([0u8; 32].into())
487
32826
	}
488

            
489
32798
	pub fn parent_relay_chain_universal_origin() -> RuntimeOrigin {
490
32798
		RuntimeOrigin::signed([1u8; 32].into())
491
32798
	}
492

            
493
65577
	pub fn sibling_parachain_origin() -> RuntimeOrigin {
494
65577
		let mut account = [0u8; 32];
495
65577
		account[..4].copy_from_slice(&SIBLING_ASSET_HUB_ID.encode()[..4]);
496
65577
		RuntimeOrigin::signed(account.into())
497
65577
	}
498

            
499
32796
	pub fn sibling_parachain_universal_origin() -> RuntimeOrigin {
500
32796
		RuntimeOrigin::signed([2u8; 32].into())
501
32796
	}
502

            
503
32793
	pub fn origin_without_sovereign_account() -> RuntimeOrigin {
504
32793
		RuntimeOrigin::signed([3u8; 32].into())
505
32793
	}
506

            
507
2
	pub fn disallowed_origin() -> RuntimeOrigin {
508
2
		RuntimeOrigin::signed([42u8; 32].into())
509
2
	}
510
}
511

            
512
impl EnsureOrigin<RuntimeOrigin> for OpenBridgeOrigin {
513
	type Success = Location;
514

            
515
32818
	fn try_origin(o: RuntimeOrigin) -> Result<Self::Success, RuntimeOrigin> {
516
32818
		let signer = o.clone().into_signer();
517
32818
		if signer == Self::parent_relay_chain_origin().into_signer() {
518
22
			return Ok(ParentRelayChainLocation::get());
519
32796
		} else if signer == Self::parent_relay_chain_universal_origin().into_signer() {
520
2
			return Ok(Location {
521
2
				parents: 2,
522
2
				interior: GlobalConsensus(RelayNetwork::get()).into(),
523
2
			});
524
32794
		} else if signer == Self::sibling_parachain_universal_origin().into_signer() {
525
2
			return Ok(Location {
526
2
				parents: 2,
527
2
				interior: [
528
2
					GlobalConsensus(RelayNetwork::get()),
529
2
					Parachain(SIBLING_ASSET_HUB_ID),
530
2
				]
531
2
				.into(),
532
2
			});
533
32792
		} else if signer == Self::origin_without_sovereign_account().into_signer() {
534
1
			return Ok(Location {
535
1
				parents: 1,
536
1
				interior: [Parachain(SIBLING_ASSET_HUB_ID), OnlyChild].into(),
537
1
			});
538
32791
		} else if signer == Self::sibling_parachain_origin().into_signer() {
539
32789
			return Ok(SiblingLocation::get());
540
2
		}
541
2

            
542
2
		Err(o)
543
32818
	}
544

            
545
	#[cfg(feature = "runtime-benchmarks")]
546
	fn try_successful_origin() -> Result<RuntimeOrigin, ()> {
547
		Ok(Self::parent_relay_chain_origin())
548
	}
549
}
550

            
551
pub(crate) type OpenBridgeOriginOf<T, I> = <T as pallet_xcm_bridge::Config<I>>::OpenBridgeOrigin;
552

            
553
14
pub(crate) fn fund_origin_sovereign_account(
554
14
	locations: &BridgeLocations,
555
14
	balance: Balance,
556
14
) -> AccountId {
557
14
	let bridge_owner_account =
558
14
		LocationToAccountId::convert_location(locations.bridge_origin_relative_location()).unwrap();
559
14
	assert_ok!(Balances::mint_into(&bridge_owner_account, balance));
560
14
	bridge_owner_account
561
14
}
562

            
563
/// Testing wrapper implementation of `LocalXcmChannelManager`, that supports storing flags in
564
/// storage to facilitate testing of `LocalXcmChannelManager` implementation.
565
pub struct TestingLocalXcmChannelManager<Bridge, Tested>(PhantomData<(Bridge, Tested)>);
566

            
567
impl<Bridge: Encode + sp_std::fmt::Debug, Tested> TestingLocalXcmChannelManager<Bridge, Tested> {
568
13
	fn suspended_key(bridge: &Bridge) -> Vec<u8> {
569
13
		[
570
13
			b"TestingLocalXcmChannelManager.Suspended",
571
13
			bridge.encode().as_slice(),
572
13
		]
573
13
		.concat()
574
13
	}
575
13
	fn resumed_key(bridge: &Bridge) -> Vec<u8> {
576
13
		[
577
13
			b"TestingLocalXcmChannelManager.Resumed",
578
13
			bridge.encode().as_slice(),
579
13
		]
580
13
		.concat()
581
13
	}
582

            
583
8
	pub fn is_bridge_suspened(bridge: &Bridge) -> bool {
584
8
		frame_support::storage::unhashed::get_or_default(&Self::suspended_key(bridge))
585
8
	}
586

            
587
9
	pub fn is_bridge_resumed(bridge: &Bridge) -> bool {
588
9
		frame_support::storage::unhashed::get_or_default(&Self::resumed_key(bridge))
589
9
	}
590
}
591

            
592
impl<Bridge: Encode + sp_std::fmt::Debug + Copy, Tested: LocalXcmChannelManager<Bridge>>
593
	LocalXcmChannelManager<Bridge> for TestingLocalXcmChannelManager<Bridge, Tested>
594
{
595
	type Error = Tested::Error;
596

            
597
5
	fn suspend_bridge(local_origin: &Location, bridge: Bridge) -> Result<(), Self::Error> {
598
5
		let result = Tested::suspend_bridge(local_origin, bridge);
599
5

            
600
5
		if result.is_ok() {
601
5
			frame_support::storage::unhashed::put(&Self::suspended_key(&bridge), &true);
602
5
		}
603

            
604
5
		result
605
5
	}
606

            
607
4
	fn resume_bridge(local_origin: &Location, bridge: Bridge) -> Result<(), Self::Error> {
608
4
		let result = Tested::resume_bridge(local_origin, bridge);
609
4

            
610
4
		if result.is_ok() {
611
4
			frame_support::storage::unhashed::put(&Self::resumed_key(&bridge), &true);
612
4
		}
613

            
614
4
		result
615
4
	}
616
}
617

            
618
/// Converts encoded call to the unpaid XCM `Transact`.
619
pub struct UpdateBridgeStatusXcmProvider;
620
impl Convert<Vec<u8>, Xcm<()>> for UpdateBridgeStatusXcmProvider {
621
2
	fn convert(encoded_call: Vec<u8>) -> Xcm<()> {
622
2
		Xcm(vec![
623
2
			UnpaidExecution {
624
2
				weight_limit: Unlimited,
625
2
				check_origin: None,
626
2
			},
627
2
			Transact {
628
2
				origin_kind: OriginKind::Xcm,
629
2
				require_weight_at_most: Weight::from_parts(200_000_000, 6144),
630
2
				call: encoded_call.into(),
631
2
			},
632
2
			ExpectTransactStatus(MaybeErrorCode::Success),
633
2
		])
634
2
	}
635
}
636

            
637
/// `SendXcm` implementation which sets `BridgeHubLocation` as origin for `ExecuteXcmOverSendXcm`.
638
pub struct FromBridgeHubLocationXcmSender<Inner>(PhantomData<Inner>);
639
impl<Inner: SendXcm> SendXcm for FromBridgeHubLocationXcmSender<Inner> {
640
	type Ticket = Inner::Ticket;
641

            
642
2
	fn validate(
643
2
		destination: &mut Option<Location>,
644
2
		message: &mut Option<Xcm<()>>,
645
2
	) -> SendResult<Self::Ticket> {
646
2
		Inner::validate(destination, message)
647
2
	}
648

            
649
2
	fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
650
2
		ExecuteXcmOverSendXcm::set_origin_for_execute(BridgeHubLocation::get());
651
2
		Inner::deliver(ticket)
652
2
	}
653
}
654

            
655
pub struct TestBlobDispatcher;
656

            
657
impl TestBlobDispatcher {
658
2
	pub fn is_dispatched() -> bool {
659
2
		frame_support::storage::unhashed::get_or_default(b"TestBlobDispatcher.Dispatched")
660
2
	}
661

            
662
3
	fn congestion_key(with: &Location) -> Vec<u8> {
663
3
		[b"TestBlobDispatcher.Congested.", with.encode().as_slice()].concat()
664
3
	}
665

            
666
1
	pub fn make_congested(with: &Location) {
667
1
		frame_support::storage::unhashed::put(&Self::congestion_key(with), &true);
668
1
	}
669
}
670

            
671
impl pallet_xcm_bridge::DispatchChannelStatusProvider for TestBlobDispatcher {
672
2
	fn is_congested(with: &Location) -> bool {
673
2
		frame_support::storage::unhashed::get_or_default(&Self::congestion_key(with))
674
2
	}
675
}
676

            
677
impl DispatchBlob for TestBlobDispatcher {
678
1
	fn dispatch_blob(_blob: Vec<u8>) -> Result<(), DispatchBlobError> {
679
1
		frame_support::storage::unhashed::put(b"TestBlobDispatcher.Dispatched", &true);
680
1
		Ok(())
681
1
	}
682
}
683

            
684
pub struct ThisUnderlyingChain;
685

            
686
impl Chain for ThisUnderlyingChain {
687
	const ID: ChainId = *b"tuch";
688

            
689
	type BlockNumber = u64;
690
	type Hash = H256;
691
	type Hasher = BlakeTwo256;
692
	type Header = SubstrateHeader;
693
	type AccountId = AccountId;
694
	type Balance = Balance;
695
	type Nonce = u64;
696
	type Signature = sp_runtime::MultiSignature;
697

            
698
	const STATE_VERSION: StateVersion = StateVersion::V1;
699

            
700
	fn max_extrinsic_size() -> u32 {
701
		u32::MAX
702
	}
703

            
704
	fn max_extrinsic_weight() -> Weight {
705
		Weight::MAX
706
	}
707
}
708

            
709
impl ChainWithMessages for ThisUnderlyingChain {
710
	const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = "WithThisChainBridgeMessages";
711
	const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 16;
712
	const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128;
713
}
714

            
715
pub type BridgedHeaderHash = H256;
716
pub type BridgedChainHeader = SubstrateHeader;
717

            
718
pub struct BridgedUnderlyingChain;
719
impl Chain for BridgedUnderlyingChain {
720
	const ID: ChainId = *b"bgdc";
721
	type BlockNumber = u64;
722
	type Hash = BridgedHeaderHash;
723
	type Hasher = BlakeTwo256;
724
	type Header = BridgedChainHeader;
725
	type AccountId = AccountId;
726
	type Balance = Balance;
727
	type Nonce = u64;
728
	type Signature = sp_runtime::MultiSignature;
729

            
730
	const STATE_VERSION: StateVersion = StateVersion::V1;
731

            
732
49205
	fn max_extrinsic_size() -> u32 {
733
49205
		4096
734
49205
	}
735

            
736
	fn max_extrinsic_weight() -> Weight {
737
		Weight::MAX
738
	}
739
}
740

            
741
impl ChainWithMessages for BridgedUnderlyingChain {
742
	const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = "WithBridgedChainBridgeMessages";
743
	const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 16;
744
	const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128;
745
}
746

            
747
pub struct BridgedHeaderChain;
748
impl bp_header_chain::HeaderChain<BridgedUnderlyingChain> for BridgedHeaderChain {
749
	fn finalized_header_state_root(
750
		_hash: HashOf<BridgedUnderlyingChain>,
751
	) -> Option<HashOf<BridgedUnderlyingChain>> {
752
		unreachable!()
753
	}
754
}
755

            
756
/// Test message dispatcher.
757
pub struct TestMessageDispatch;
758

            
759
impl TestMessageDispatch {
760
	pub fn deactivate(lane: TestLaneIdType) {
761
		frame_support::storage::unhashed::put(&(b"inactive", lane).encode()[..], &false);
762
	}
763
}
764

            
765
impl MessageDispatch for TestMessageDispatch {
766
	type DispatchPayload = Vec<u8>;
767
	type DispatchLevelResult = ();
768
	type LaneId = TestLaneIdType;
769

            
770
37
	fn is_active(lane: Self::LaneId) -> bool {
771
37
		frame_support::storage::unhashed::take::<bool>(&(b"inactive", lane).encode()[..])
772
37
			!= Some(false)
773
37
	}
774

            
775
	fn dispatch_weight(
776
		_message: &mut DispatchMessage<Self::DispatchPayload, Self::LaneId>,
777
	) -> Weight {
778
		Weight::zero()
779
	}
780

            
781
	fn dispatch(
782
		_: DispatchMessage<Self::DispatchPayload, Self::LaneId>,
783
	) -> MessageDispatchResult<Self::DispatchLevelResult> {
784
		MessageDispatchResult {
785
			unspent_weight: Weight::zero(),
786
			dispatch_level_result: (),
787
		}
788
	}
789
}
790

            
791
/// Return test externalities to use in tests.
792
35
pub fn new_test_ext() -> sp_io::TestExternalities {
793
35
	let t = frame_system::GenesisConfig::<TestRuntime>::default()
794
35
		.build_storage()
795
35
		.unwrap();
796
35
	sp_io::TestExternalities::new(t)
797
35
}
798

            
799
/// Run pallet test.
800
35
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
801
35
	new_test_ext().execute_with(test)
802
35
}