1
// Copyright 2025 Moonbeam Foundation.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam 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
// Moonbeam 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 Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
extern crate alloc;
18

            
19
use crate::xcm_config::{SelfLocation, UniversalLocation};
20
use crate::{
21
	moonbeam_weights, Balances, BridgeKusamaMessages, BridgeXcmOverMoonriver, MessageQueue,
22
	PolkadotXcm, Runtime, RuntimeEvent, RuntimeHoldReason,
23
};
24
use alloc::collections::btree_set::BTreeSet;
25
use bp_moonbeam::bp_kusama;
26
use bp_parachains::SingleParaStoredHeaderDataBuilder;
27
use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge;
28
use frame_support::pallet_prelude::PalletInfoAccess;
29
use frame_support::traits::{Contains, Everything};
30
use frame_support::{parameter_types, traits::ConstU32};
31
use frame_system::{EnsureNever, EnsureRoot};
32
use moonbeam_core_primitives::{AccountId, Balance};
33
use moonbeam_runtime_common::bridge::{CongestionManager, LocalBlobDispatcher};
34
use pallet_xcm_bridge::XcmAsPlainPayload;
35
use polkadot_parachain::primitives::Sibling;
36
use xcm::latest::{Junction, Location};
37
use xcm::prelude::{GlobalConsensus, InteriorLocation, NetworkId, PalletInstance};
38
use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia};
39

            
40
parameter_types! {
41
	pub BridgePolkadotToKusamaMessagesPalletInstance: InteriorLocation = [PalletInstance(<BridgeKusamaMessages as PalletInfoAccess>::index() as u8)].into();
42
	pub KusamaGlobalConsensusNetwork: NetworkId = NetworkId::Kusama;
43
	pub KusamaGlobalConsensusNetworkLocation: Location = Location::new(
44
		2,
45
		[GlobalConsensus(KusamaGlobalConsensusNetwork::get())]
46
	);
47

            
48
	pub const RelayChainHeadersToKeep: u32 = 1024;
49
	pub const ParachainHeadsToKeep: u32 = 64;
50

            
51
	pub const KusamaBridgeParachainPalletName: &'static str = bp_kusama::PARAS_PALLET_NAME;
52
	pub const MaxKusamaParaHeadDataSize: u32 = bp_kusama::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE;
53

            
54
	/// Universal aliases
55
	pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
56
		alloc::vec![
57
			// Messages from Moonriver will have Kusama as global consensus and
58
			// will be put in the message queue with "Here" as origin
59
			(SelfLocation::get(), GlobalConsensus(KusamaGlobalConsensusNetwork::get()))
60
		]
61
	);
62

            
63
	pub storage BridgeDeposit: Balance = 0;
64
}
65

            
66
impl Contains<(Location, Junction)> for UniversalAliases {
67
6
	fn contains(alias: &(Location, Junction)) -> bool {
68
6
		UniversalAliases::get().contains(alias)
69
6
	}
70
}
71

            
72
/// Add GRANDPA bridge pallet to track Kusama relay chain.
73
pub type BridgeGrandpaKusamaInstance = pallet_bridge_grandpa::Instance1;
74
impl pallet_bridge_grandpa::Config<BridgeGrandpaKusamaInstance> for Runtime {
75
	type RuntimeEvent = RuntimeEvent;
76
	type BridgedChain = bp_kusama::Kusama;
77
	type MaxFreeHeadersPerBlock = ConstU32<4>;
78
	type FreeHeadersInterval = ConstU32<5>;
79
	type HeadersToKeep = RelayChainHeadersToKeep;
80
	type WeightInfo = moonbeam_weights::pallet_bridge_grandpa::WeightInfo<Runtime>;
81
}
82

            
83
/// Add parachain bridge pallet to track Moonriver parachain.
84
pub type BridgeMoonriverInstance = pallet_bridge_parachains::Instance1;
85
impl pallet_bridge_parachains::Config<BridgeMoonriverInstance> for Runtime {
86
	type RuntimeEvent = RuntimeEvent;
87
	type BridgesGrandpaPalletInstance = BridgeGrandpaKusamaInstance;
88
	type ParasPalletName = KusamaBridgeParachainPalletName;
89
	type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder<bp_moonriver::Moonriver>;
90
	type HeadsToKeep = ParachainHeadsToKeep;
91
	type MaxParaHeadDataSize = MaxKusamaParaHeadDataSize;
92
	type WeightInfo = moonbeam_weights::pallet_bridge_parachains::WeightInfo<Runtime>;
93
}
94

            
95
/// Add XCM messages support for Moonbeam->Moonriver
96
pub type WithKusamaMessagesInstance = pallet_bridge_messages::Instance1;
97
impl pallet_bridge_messages::Config<WithKusamaMessagesInstance> for Runtime {
98
	type RuntimeEvent = RuntimeEvent;
99

            
100
	type ThisChain = bp_moonbeam::Moonbeam;
101
	type BridgedChain = bp_moonriver::Moonriver;
102
	type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders<
103
		Runtime,
104
		BridgeMoonriverInstance,
105
		bp_moonriver::Moonriver,
106
	>;
107

            
108
	type OutboundPayload = XcmAsPlainPayload;
109
	type InboundPayload = XcmAsPlainPayload;
110
	type LaneId = bp_moonbeam::LaneId;
111

            
112
	type DeliveryPayments = ();
113
	type DeliveryConfirmationPayments = (); // Only necessary if we want to reward relayers
114

            
115
	type MessageDispatch = BridgeXcmOverMoonriver;
116
	type OnMessagesDelivered = BridgeXcmOverMoonriver;
117
	type WeightInfo = moonbeam_weights::pallet_bridge_messages::WeightInfo<Runtime>;
118
}
119

            
120
/// Add support for the export and dispatch of XCM programs withing
121
/// `WithKusamaMessagesInstance`.
122
pub type XcmOverKusamaInstance = pallet_xcm_bridge::Instance1;
123
impl pallet_xcm_bridge::Config<XcmOverKusamaInstance> for Runtime {
124
	type RuntimeEvent = RuntimeEvent;
125

            
126
	type UniversalLocation = UniversalLocation;
127
	type BridgedNetwork = KusamaGlobalConsensusNetworkLocation;
128
	type BridgeMessagesPalletInstance = WithKusamaMessagesInstance;
129

            
130
	type MessageExportPrice = ();
131
	type DestinationVersion =
132
		XcmVersionOfDestAndRemoteBridge<PolkadotXcm, bp_moonriver::GlobalConsensusLocation>;
133

            
134
	type ForceOrigin = EnsureRoot<AccountId>;
135
	// We don't want to allow creating bridges.
136
	type OpenBridgeOrigin = EnsureNever<Location>;
137
	// Converter aligned with `OpenBridgeOrigin`.
138
	type BridgeOriginAccountIdConverter = (
139
		ParentIsPreset<AccountId>,
140
		SiblingParachainConvertsVia<Sibling, AccountId>,
141
	);
142

            
143
	type BridgeDeposit = BridgeDeposit;
144
	type Currency = Balances;
145
	type RuntimeHoldReason = RuntimeHoldReason;
146
	// Don't require a deposit, since we don't allow opening new bridges.
147
	type AllowWithoutBridgeDeposit = Everything;
148
	type LocalXcmChannelManager = CongestionManager<Runtime>;
149
	// Dispatching inbound messages from the bridge and managing congestion with the local
150
	// receiving/destination chain
151
	type BlobDispatcher = LocalBlobDispatcher<
152
		MessageQueue,
153
		UniversalLocation,
154
		BridgePolkadotToKusamaMessagesPalletInstance,
155
	>;
156
}
157

            
158
#[cfg(feature = "runtime-benchmarks")]
159
pub mod benchmarking {
160
	use crate::bridge_config::KusamaGlobalConsensusNetwork;
161
	use crate::Runtime;
162
	use bp_messages::source_chain::FromBridgedChainMessagesDeliveryProof;
163
	use bp_messages::target_chain::FromBridgedChainMessagesProof;
164
	use pallet_bridge_messages::LaneIdOf;
165
	use xcm::latest::{InteriorLocation, Location, NetworkId};
166
	use xcm::prelude::{GlobalConsensus, Parachain};
167

            
168
	/// Proof of messages, coming from Moonbeam.
169
	pub type FromMoonriverMessagesProof<MI> =
170
		FromBridgedChainMessagesProof<bp_moonriver::Hash, LaneIdOf<Runtime, MI>>;
171
	/// Messages delivery proof for Moonbeam -> Moonriver.
172
	pub type ToMoonriverMessagesDeliveryProof<MI> =
173
		FromBridgedChainMessagesDeliveryProof<bp_moonriver::Hash, LaneIdOf<Runtime, MI>>;
174

            
175
	pub(crate) fn open_bridge_for_benchmarks<R, XBHI, C>(
176
		with: pallet_xcm_bridge::LaneIdOf<R, XBHI>,
177
		sibling_para_id: u32,
178
	) -> InteriorLocation
179
	where
180
		R: pallet_xcm_bridge::Config<XBHI>,
181
		XBHI: 'static,
182
		C: xcm_executor::traits::ConvertLocation<
183
			bp_runtime::AccountIdOf<pallet_xcm_bridge::ThisChainOf<R, XBHI>>,
184
		>,
185
	{
186
		use alloc::boxed::Box;
187
		use pallet_xcm_bridge::{Bridge, BridgeId, BridgeState};
188
		use sp_runtime::traits::Zero;
189
		use xcm::VersionedInteriorLocation;
190

            
191
		// insert bridge metadata
192
		let lane_id = with;
193
		let sibling_parachain = Location::new(1, [Parachain(sibling_para_id)]);
194
		let universal_source = [
195
			GlobalConsensus(NetworkId::Kusama),
196
			Parachain(sibling_para_id),
197
		]
198
		.into();
199
		let universal_destination = [
200
			GlobalConsensus(KusamaGlobalConsensusNetwork::get()),
201
			Parachain(<bp_moonbeam::Moonbeam as bp_runtime::Parachain>::PARACHAIN_ID),
202
		]
203
		.into();
204
		let bridge_id = BridgeId::new(&universal_source, &universal_destination);
205

            
206
		// insert only bridge metadata, because the benchmarks create lanes
207
		pallet_xcm_bridge::Bridges::<R, XBHI>::insert(
208
			bridge_id,
209
			Bridge {
210
				bridge_origin_relative_location: Box::new(sibling_parachain.clone().into()),
211
				bridge_origin_universal_location: Box::new(VersionedInteriorLocation::from(
212
					universal_source.clone(),
213
				)),
214
				bridge_destination_universal_location: Box::new(VersionedInteriorLocation::from(
215
					universal_destination,
216
				)),
217
				state: BridgeState::Opened,
218
				bridge_owner_account: C::convert_location(&sibling_parachain)
219
					.expect("valid AccountId"),
220
				deposit: Zero::zero(),
221
				lane_id,
222
			},
223
		);
224
		pallet_xcm_bridge::LaneToBridge::<R, XBHI>::insert(lane_id, bridge_id);
225

            
226
		universal_source
227
	}
228
}