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
	moonriver_weights, Balances, BridgePolkadotMessages, BridgeXcmOverMoonbeam, MessageQueue,
22
	PolkadotXcm, Runtime, RuntimeEvent, RuntimeHoldReason,
23
};
24
use alloc::collections::btree_set::BTreeSet;
25
use bp_parachains::SingleParaStoredHeaderDataBuilder;
26
use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge;
27
use frame_support::pallet_prelude::PalletInfoAccess;
28
use frame_support::traits::{Contains, Everything};
29
use frame_support::{parameter_types, traits::ConstU32};
30
use frame_system::{EnsureNever, EnsureRoot};
31
use moonbeam_core_primitives::{AccountId, Balance};
32
use moonbeam_runtime_common::bridge::{CongestionManager, LocalBlobDispatcher};
33
use pallet_xcm_bridge::XcmAsPlainPayload;
34
use polkadot_parachain::primitives::Sibling;
35
use xcm::latest::{InteriorLocation, Junction, Location, NetworkId};
36
use xcm::prelude::{GlobalConsensus, PalletInstance};
37
use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia};
38

            
39
parameter_types! {
40
	pub BridgeKusamaToPolkadotMessagesPalletInstance: InteriorLocation = [PalletInstance(<BridgePolkadotMessages as PalletInfoAccess>::index() as u8)].into();
41
	pub PolkadotGlobalConsensusNetwork: NetworkId = NetworkId::Polkadot;
42
	pub PolkadotGlobalConsensusNetworkLocation: Location = Location::new(
43
		2,
44
		[GlobalConsensus(PolkadotGlobalConsensusNetwork::get())]
45
	);
46

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

            
50
	pub const PolkadotBridgeParachainPalletName: &'static str = bp_polkadot::PARAS_PALLET_NAME;
51
	pub const MaxPolkadotParaHeadDataSize: u32 = bp_polkadot::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE;
52

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

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

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

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

            
82
/// Add parachain bridge pallet to track Moonbeam parachain.
83
pub type BridgeMoonbeamInstance = pallet_bridge_parachains::Instance1;
84
impl pallet_bridge_parachains::Config<BridgeMoonbeamInstance> for Runtime {
85
	type RuntimeEvent = RuntimeEvent;
86
	type BridgesGrandpaPalletInstance = BridgeGrandpaPolkadotInstance;
87
	type ParasPalletName = PolkadotBridgeParachainPalletName;
88
	type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder<bp_moonbeam::Moonbeam>;
89
	type HeadsToKeep = ParachainHeadsToKeep;
90
	type MaxParaHeadDataSize = MaxPolkadotParaHeadDataSize;
91
	type WeightInfo = moonriver_weights::pallet_bridge_parachains::WeightInfo<Runtime>;
92
}
93

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

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

            
107
	type OutboundPayload = XcmAsPlainPayload;
108
	type InboundPayload = XcmAsPlainPayload;
109
	type LaneId = bp_moonriver::LaneId;
110

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

            
114
	type MessageDispatch = BridgeXcmOverMoonbeam;
115
	type OnMessagesDelivered = BridgeXcmOverMoonbeam;
116
	type WeightInfo = moonriver_weights::pallet_bridge_messages::WeightInfo<Runtime>;
117
}
118

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

            
125
	type UniversalLocation = UniversalLocation;
126
	type BridgedNetwork = PolkadotGlobalConsensusNetworkLocation;
127
	type BridgeMessagesPalletInstance = WithPolkadotMessagesInstance;
128
	type MessageExportPrice = ();
129
	type DestinationVersion =
130
		XcmVersionOfDestAndRemoteBridge<PolkadotXcm, bp_moonbeam::GlobalConsensusLocation>;
131

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

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

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

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

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

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

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

            
224
		universal_source
225
	}
226
}