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::{
46
	SendError::{MissingArgument, NotApplicable},
47
	ROCOCO_GENESIS_HASH,
48
};
49
use xcm::prelude::*;
50
use xcm_builder::{
51
	ensure_is_remote, AllowUnpaidExecutionFrom, DispatchBlob, DispatchBlobError, FixedWeightBounds,
52
	InspectMessageQueues, NetworkExportTable, NetworkExportTableItem, ParentIsPreset,
53
	SiblingParachainConvertsVia, SovereignPaidRemoteExporter,
54
};
55
use xcm_executor::traits::{validate_export, ExportXcm};
56
use xcm_executor::{
57
	traits::{ConvertLocation, ConvertOrigin},
58
	XcmExecutor,
59
};
60

            
61
pub type AccountId = AccountId32;
62
pub type Balance = u64;
63
type Block = frame_system::mocking::MockBlock<TestRuntime>;
64

            
65
/// Lane identifier type used for tests.
66
pub type TestLaneIdType = HashedLaneId;
67

            
68
pub const SIBLING_ASSET_HUB_ID: u32 = 2001;
69
pub const THIS_BRIDGE_HUB_ID: u32 = 2002;
70
pub const BRIDGED_ASSET_HUB_ID: u32 = 1001;
71

            
72
919648
frame_support::construct_runtime! {
73
1328501
	pub enum TestRuntime {
74
1328501
		System: frame_system,
75
1328501
		Balances: pallet_balances,
76
1328501
		Messages: pallet_bridge_messages,
77
1328501
		XcmOverBridge: pallet_xcm_bridge,
78
1328501
		XcmOverBridgeWrappedWithExportMessageRouter: pallet_xcm_bridge_router = 57,
79
1328501
		XcmOverBridgeByExportXcmRouter: pallet_xcm_bridge_router::<Instance2> = 69,
80
1328501
	}
81
1328501
}
82

            
83
parameter_types! {
84
	pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 };
85
	pub const ExistentialDeposit: Balance = 1;
86
}
87

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

            
96
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
97
impl pallet_balances::Config for TestRuntime {
98
	type AccountStore = System;
99
}
100

            
101
impl pallet_bridge_messages::Config for TestRuntime {
102
	type RuntimeEvent = RuntimeEvent;
103
	type WeightInfo = TestMessagesWeights;
104

            
105
	type ThisChain = ThisUnderlyingChain;
106
	type BridgedChain = BridgedUnderlyingChain;
107
	type BridgedHeaderChain = BridgedHeaderChain;
108

            
109
	type OutboundPayload = Vec<u8>;
110
	type InboundPayload = Vec<u8>;
111
	type LaneId = TestLaneIdType;
112

            
113
	type DeliveryPayments = ();
114
	type DeliveryConfirmationPayments = ();
115
	type OnMessagesDelivered = ();
116

            
117
	type MessageDispatch = TestMessageDispatch;
118
}
119

            
120
pub struct TestMessagesWeights;
121

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

            
149
impl pallet_bridge_messages::WeightInfoExt for TestMessagesWeights {
150
	fn expected_extra_storage_proof_size() -> u32 {
151
		0
152
	}
153

            
154
	fn receive_messages_proof_overhead_from_runtime() -> Weight {
155
		Weight::zero()
156
	}
157

            
158
	fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
159
		Weight::zero()
160
	}
161
}
162

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

            
173
	pub const BridgedRelayNetwork: NetworkId = NetworkId::ByGenesis([1; 32]);
174
	pub BridgedRelayNetworkLocation: Location = (Parent, GlobalConsensus(BridgedRelayNetwork::get())).into();
175
	pub BridgedRelativeDestination: InteriorLocation = [Parachain(BRIDGED_ASSET_HUB_ID)].into();
176
	pub BridgedUniversalDestination: InteriorLocation = [GlobalConsensus(BridgedRelayNetwork::get()), Parachain(BRIDGED_ASSET_HUB_ID)].into();
177
	pub const NonBridgedRelayNetwork: NetworkId = NetworkId::ByGenesis(ROCOCO_GENESIS_HASH);
178

            
179
	pub const BridgeDeposit: Balance = 100_000;
180

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

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

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

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

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

            
236
8194
	fn deliver(ticket: Exporter::Ticket) -> Result<XcmHash, SendError> {
237
8194
		Exporter::deliver(ticket)
238
8194
	}
239
}
240

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

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

            
262
impl pallet_xcm_bridge::Config for TestRuntime {
263
	type RuntimeEvent = RuntimeEvent;
264
	type WeightInfo = ();
265

            
266
	type UniversalLocation = UniversalLocation;
267
	type BridgedNetwork = BridgedRelayNetworkLocation;
268
	type BridgeMessagesPalletInstance = ();
269

            
270
	type MessageExportPrice = ();
271
	type DestinationVersion = AlwaysLatest;
272

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

            
281
	type BridgeDeposit = BridgeDeposit;
282
	type Currency = Balances;
283
	type RuntimeHoldReason = RuntimeHoldReason;
284
	type AllowWithoutBridgeDeposit = (Equals<ParentRelayChainLocation>, Equals<HereLocation>);
285

            
286
	type LocalXcmChannelManager = TestLocalXcmChannelManager;
287
	type BlobDispatcher = BlobDispatcherWithChannelStatus<TestBlobDispatcher, TestBlobDispatcher>;
288
	type CongestionLimits = TestCongestionLimits;
289
}
290

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

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

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

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

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

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

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

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

            
424
thread_local! {
425
	pub static EXECUTE_XCM_ORIGIN: RefCell<Option<Location>> = RefCell::new(None);
426
}
427

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

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

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

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

            
454
8197
		Ok(hash)
455
8197
	}
456
}
457
impl InspectMessageQueues for ExecuteXcmOverSendXcm {
458
	fn clear_messages() {
459
		todo!()
460
	}
461

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

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

            
482
parameter_types! {
483
	pub ParentRelayChainLocation: Location = Location { parents: 1, interior: Here };
484
}
485
pub struct OpenBridgeOrigin;
486

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

            
492
32798
	pub fn parent_relay_chain_universal_origin() -> RuntimeOrigin {
493
32798
		RuntimeOrigin::signed([1u8; 32].into())
494
32798
	}
495

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

            
502
32796
	pub fn sibling_parachain_universal_origin() -> RuntimeOrigin {
503
32796
		RuntimeOrigin::signed([2u8; 32].into())
504
32796
	}
505

            
506
32793
	pub fn origin_without_sovereign_account() -> RuntimeOrigin {
507
32793
		RuntimeOrigin::signed([3u8; 32].into())
508
32793
	}
509

            
510
2
	pub fn disallowed_origin() -> RuntimeOrigin {
511
2
		RuntimeOrigin::signed([42u8; 32].into())
512
2
	}
513
}
514

            
515
impl EnsureOrigin<RuntimeOrigin> for OpenBridgeOrigin {
516
	type Success = Location;
517

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

            
545
2
		Err(o)
546
32818
	}
547

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

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

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

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

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

            
586
8
	pub fn is_bridge_suspened(bridge: &Bridge) -> bool {
587
8
		frame_support::storage::unhashed::get_or_default(&Self::suspended_key(bridge))
588
8
	}
589

            
590
9
	pub fn is_bridge_resumed(bridge: &Bridge) -> bool {
591
9
		frame_support::storage::unhashed::get_or_default(&Self::resumed_key(bridge))
592
9
	}
593
}
594

            
595
impl<Bridge: Encode + sp_std::fmt::Debug + Copy, Tested: LocalXcmChannelManager<Bridge>>
596
	LocalXcmChannelManager<Bridge> for TestingLocalXcmChannelManager<Bridge, Tested>
597
{
598
	type Error = Tested::Error;
599

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

            
603
5
		if result.is_ok() {
604
5
			frame_support::storage::unhashed::put(&Self::suspended_key(&bridge), &true);
605
5
		}
606

            
607
5
		result
608
5
	}
609

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

            
613
4
		if result.is_ok() {
614
4
			frame_support::storage::unhashed::put(&Self::resumed_key(&bridge), &true);
615
4
		}
616

            
617
4
		result
618
4
	}
619
}
620

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

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

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

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

            
658
pub struct TestBlobDispatcher;
659

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

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

            
669
1
	pub fn make_congested(with: &Location) {
670
1
		frame_support::storage::unhashed::put(&Self::congestion_key(with), &true);
671
1
	}
672
}
673

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

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

            
687
pub struct ThisUnderlyingChain;
688

            
689
impl Chain for ThisUnderlyingChain {
690
	const ID: ChainId = *b"tuch";
691

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

            
701
	const STATE_VERSION: StateVersion = StateVersion::V1;
702

            
703
	fn max_extrinsic_size() -> u32 {
704
		u32::MAX
705
	}
706

            
707
	fn max_extrinsic_weight() -> Weight {
708
		Weight::MAX
709
	}
710
}
711

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

            
718
pub type BridgedHeaderHash = H256;
719
pub type BridgedChainHeader = SubstrateHeader;
720

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

            
733
	const STATE_VERSION: StateVersion = StateVersion::V1;
734

            
735
49205
	fn max_extrinsic_size() -> u32 {
736
49205
		4096
737
49205
	}
738

            
739
	fn max_extrinsic_weight() -> Weight {
740
		Weight::MAX
741
	}
742
}
743

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

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

            
759
/// Test message dispatcher.
760
pub struct TestMessageDispatch;
761

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

            
768
impl MessageDispatch for TestMessageDispatch {
769
	type DispatchPayload = Vec<u8>;
770
	type DispatchLevelResult = ();
771
	type LaneId = TestLaneIdType;
772

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

            
778
	fn dispatch_weight(
779
		_message: &mut DispatchMessage<Self::DispatchPayload, Self::LaneId>,
780
	) -> Weight {
781
		Weight::zero()
782
	}
783

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

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

            
802
/// Run pallet test.
803
35
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
804
35
	new_test_ext().execute_with(test)
805
35
}