moonbeam_runtime/
bridge_config.rs

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
17extern crate alloc;
18
19use crate::xcm_config::{SelfLocation, UniversalLocation};
20use crate::{
21	moonbeam_weights, Balances, BridgeKusamaMessages, BridgeXcmOverMoonriver, MessageQueue,
22	PolkadotXcm, Runtime, RuntimeEvent, RuntimeHoldReason,
23};
24use alloc::collections::btree_set::BTreeSet;
25use bp_moonbeam::bp_kusama;
26use bp_parachains::SingleParaStoredHeaderDataBuilder;
27use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge;
28use frame_support::pallet_prelude::PalletInfoAccess;
29use frame_support::traits::{Contains, Everything};
30use frame_support::{parameter_types, traits::ConstU32};
31use frame_system::{EnsureNever, EnsureRoot};
32use moonbeam_core_primitives::{AccountId, Balance};
33use moonbeam_runtime_common::bridge::{CongestionManager, LocalBlobDispatcher};
34use pallet_xcm_bridge::XcmAsPlainPayload;
35use polkadot_parachain::primitives::Sibling;
36use xcm::latest::{Junction, Location};
37use xcm::prelude::{GlobalConsensus, InteriorLocation, NetworkId, PalletInstance};
38use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia};
39
40parameter_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
66impl Contains<(Location, Junction)> for UniversalAliases {
67	fn contains(alias: &(Location, Junction)) -> bool {
68		UniversalAliases::get().contains(alias)
69	}
70}
71
72/// Add GRANDPA bridge pallet to track Kusama relay chain.
73pub type BridgeGrandpaKusamaInstance = pallet_bridge_grandpa::Instance1;
74impl 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.
84pub type BridgeMoonriverInstance = pallet_bridge_parachains::Instance1;
85impl 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 OnNewHead = ();
93	type WeightInfo = moonbeam_weights::pallet_bridge_parachains::WeightInfo<Runtime>;
94}
95
96/// Add XCM messages support for Moonbeam->Moonriver
97pub type WithKusamaMessagesInstance = pallet_bridge_messages::Instance1;
98impl pallet_bridge_messages::Config<WithKusamaMessagesInstance> for Runtime {
99	type RuntimeEvent = RuntimeEvent;
100
101	type ThisChain = bp_moonbeam::Moonbeam;
102	type BridgedChain = bp_moonriver::Moonriver;
103	type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders<
104		Runtime,
105		BridgeMoonriverInstance,
106		bp_moonriver::Moonriver,
107	>;
108
109	type OutboundPayload = XcmAsPlainPayload;
110	type InboundPayload = XcmAsPlainPayload;
111	type LaneId = bp_moonbeam::LaneId;
112
113	type DeliveryPayments = ();
114	type DeliveryConfirmationPayments = (); // Only necessary if we want to reward relayers
115
116	type MessageDispatch = BridgeXcmOverMoonriver;
117	type OnMessagesDelivered = BridgeXcmOverMoonriver;
118	type WeightInfo = moonbeam_weights::pallet_bridge_messages::WeightInfo<Runtime>;
119}
120
121/// Add support for the export and dispatch of XCM programs withing
122/// `WithKusamaMessagesInstance`.
123pub type XcmOverKusamaInstance = pallet_xcm_bridge::Instance1;
124impl pallet_xcm_bridge::Config<XcmOverKusamaInstance> for Runtime {
125	type RuntimeEvent = RuntimeEvent;
126
127	type UniversalLocation = UniversalLocation;
128	type BridgedNetwork = KusamaGlobalConsensusNetworkLocation;
129	type BridgeMessagesPalletInstance = WithKusamaMessagesInstance;
130
131	type MessageExportPrice = ();
132	type DestinationVersion =
133		XcmVersionOfDestAndRemoteBridge<PolkadotXcm, bp_moonriver::GlobalConsensusLocation>;
134
135	type ForceOrigin = EnsureRoot<AccountId>;
136	// We don't want to allow creating bridges.
137	type OpenBridgeOrigin = EnsureNever<Location>;
138	// Converter aligned with `OpenBridgeOrigin`.
139	type BridgeOriginAccountIdConverter = (
140		ParentIsPreset<AccountId>,
141		SiblingParachainConvertsVia<Sibling, AccountId>,
142	);
143
144	type BridgeDeposit = BridgeDeposit;
145	type Currency = Balances;
146	type RuntimeHoldReason = RuntimeHoldReason;
147	// Don't require a deposit, since we don't allow opening new bridges.
148	type AllowWithoutBridgeDeposit = Everything;
149	type LocalXcmChannelManager = CongestionManager<Runtime>;
150	// Dispatching inbound messages from the bridge and managing congestion with the local
151	// receiving/destination chain
152	type BlobDispatcher = LocalBlobDispatcher<
153		MessageQueue,
154		UniversalLocation,
155		BridgePolkadotToKusamaMessagesPalletInstance,
156	>;
157}
158
159#[cfg(feature = "runtime-benchmarks")]
160pub mod benchmarking {
161	use crate::bridge_config::KusamaGlobalConsensusNetwork;
162	use crate::Runtime;
163	use bp_messages::source_chain::FromBridgedChainMessagesDeliveryProof;
164	use bp_messages::target_chain::FromBridgedChainMessagesProof;
165	use pallet_bridge_messages::LaneIdOf;
166	use xcm::latest::{InteriorLocation, Location, NetworkId};
167	use xcm::prelude::{GlobalConsensus, Parachain};
168
169	/// Proof of messages, coming from Moonbeam.
170	pub type FromMoonriverMessagesProof<MI> =
171		FromBridgedChainMessagesProof<bp_moonriver::Hash, LaneIdOf<Runtime, MI>>;
172	/// Messages delivery proof for Moonbeam -> Moonriver.
173	pub type ToMoonriverMessagesDeliveryProof<MI> =
174		FromBridgedChainMessagesDeliveryProof<bp_moonriver::Hash, LaneIdOf<Runtime, MI>>;
175
176	pub(crate) fn open_bridge_for_benchmarks<R, XBHI, C>(
177		with: pallet_xcm_bridge::LaneIdOf<R, XBHI>,
178		sibling_para_id: u32,
179	) -> InteriorLocation
180	where
181		R: pallet_xcm_bridge::Config<XBHI>,
182		XBHI: 'static,
183		C: xcm_executor::traits::ConvertLocation<
184			bp_runtime::AccountIdOf<pallet_xcm_bridge::ThisChainOf<R, XBHI>>,
185		>,
186	{
187		use alloc::boxed::Box;
188		use pallet_xcm_bridge::{Bridge, BridgeId, BridgeState};
189		use sp_runtime::traits::Zero;
190		use xcm::VersionedInteriorLocation;
191
192		// insert bridge metadata
193		let lane_id = with;
194		let sibling_parachain = Location::new(1, [Parachain(sibling_para_id)]);
195		let universal_source = [
196			GlobalConsensus(NetworkId::Kusama),
197			Parachain(sibling_para_id),
198		]
199		.into();
200		let universal_destination = [
201			GlobalConsensus(KusamaGlobalConsensusNetwork::get()),
202			Parachain(<bp_moonbeam::Moonbeam as bp_runtime::Parachain>::PARACHAIN_ID),
203		]
204		.into();
205		let bridge_id = BridgeId::new(&universal_source, &universal_destination);
206
207		// insert only bridge metadata, because the benchmarks create lanes
208		pallet_xcm_bridge::Bridges::<R, XBHI>::insert(
209			bridge_id,
210			Bridge {
211				bridge_origin_relative_location: Box::new(sibling_parachain.clone().into()),
212				bridge_origin_universal_location: Box::new(VersionedInteriorLocation::from(
213					universal_source.clone(),
214				)),
215				bridge_destination_universal_location: Box::new(VersionedInteriorLocation::from(
216					universal_destination,
217				)),
218				state: BridgeState::Opened,
219				bridge_owner_account: C::convert_location(&sibling_parachain)
220					.expect("valid AccountId"),
221				deposit: Zero::zero(),
222				lane_id,
223			},
224		);
225		pallet_xcm_bridge::LaneToBridge::<R, XBHI>::insert(lane_id, bridge_id);
226
227		universal_source
228	}
229}