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_moonriver::bp_polkadot;
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::{InteriorLocation, Junction, Location, NetworkId};
37
use xcm::prelude::{GlobalConsensus, PalletInstance};
38
use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia};
39

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

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

            
51
	pub const PolkadotBridgeParachainPalletName: &'static str = bp_polkadot::PARAS_PALLET_NAME;
52
	pub const MaxPolkadotParaHeadDataSize: u32 = bp_polkadot::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 Moonbeam will have Polkadot as global consensus and
58
			// will be put in the message queue with "Here" as origin
59
			(SelfLocation::get(), GlobalConsensus(PolkadotGlobalConsensusNetwork::get()))
60
		]
61
	);
62

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
225
		universal_source
226
	}
227
}