referrerpolicy=no-referrer-when-downgrade

bridge_hub_rococo_runtime/
bridge_to_bulletin_config.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! Bridge definitions used on BridgeHubRococo for bridging to Rococo Bulletin.
18//!
19//! Rococo Bulletin chain will be the 1:1 copy of the Polkadot Bulletin, so we
20//! are reusing Polkadot Bulletin chain primitives everywhere here.
21
22use crate::{
23	bridge_common_config::RelayersForPermissionlessLanesInstance, weights,
24	xcm_config::UniversalLocation, AccountId, Balance, Balances, BridgeRococoBulletinGrandpa,
25	BridgeRococoBulletinMessages, Runtime, RuntimeEvent, RuntimeHoldReason, XcmOverRococoBulletin,
26	XcmRouter,
27};
28use bp_messages::{
29	source_chain::FromBridgedChainMessagesDeliveryProof,
30	target_chain::FromBridgedChainMessagesProof, LegacyLaneId,
31};
32
33use frame_support::{
34	parameter_types,
35	traits::{Equals, PalletInfoAccess},
36};
37use frame_system::{EnsureNever, EnsureRoot};
38use pallet_bridge_messages::LaneIdOf;
39use pallet_bridge_relayers::extension::{
40	BridgeRelayersTransactionExtension, WithMessagesExtensionConfig,
41};
42use pallet_xcm_bridge_hub::XcmAsPlainPayload;
43use polkadot_parachain_primitives::primitives::Sibling;
44use testnet_parachains_constants::rococo::currency::UNITS as ROC;
45use xcm::{
46	latest::prelude::*,
47	prelude::{InteriorLocation, NetworkId},
48	AlwaysV5,
49};
50use xcm_builder::{BridgeBlobDispatcher, ParentIsPreset, SiblingParachainConvertsVia};
51
52parameter_types! {
53	/// Interior location (relative to this runtime) of the with-RococoBulletin messages pallet.
54	pub BridgeRococoToRococoBulletinMessagesPalletInstance: InteriorLocation = [
55		PalletInstance(<BridgeRococoBulletinMessages as PalletInfoAccess>::index() as u8)
56	].into();
57	/// Rococo Bulletin Network identifier.
58	pub RococoBulletinGlobalConsensusNetwork: NetworkId = NetworkId::PolkadotBulletin;
59	/// Relative location of the Rococo Bulletin chain.
60	pub RococoBulletinGlobalConsensusNetworkLocation: Location = Location::new(
61		2,
62		[GlobalConsensus(RococoBulletinGlobalConsensusNetwork::get())]
63	);
64
65	// see the `FEE_BOOST_PER_RELAY_HEADER` constant get the meaning of this value
66	pub PriorityBoostPerRelayHeader: u64 = 58_014_163_614_163;
67
68	/// Priority boost that the registered relayer receives for every additional message in the message
69	/// delivery transaction.
70	///
71	/// It is determined semi-automatically - see `FEE_BOOST_PER_MESSAGE` constant to get the
72	/// meaning of this value.
73	pub PriorityBoostPerMessage: u64 = 364_088_888_888_888;
74
75	/// PeopleRococo location
76	pub PeopleRococoLocation: Location = Location::new(1, [Parachain(rococo_runtime_constants::system_parachain::PEOPLE_ID)]);
77
78	pub storage BridgeDeposit: Balance = 5 * ROC;
79}
80
81/// Proof of messages, coming from Rococo Bulletin chain.
82pub type FromRococoBulletinMessagesProof<MI> =
83	FromBridgedChainMessagesProof<bp_polkadot_bulletin::Hash, LaneIdOf<Runtime, MI>>;
84/// Messages delivery proof for Rococo Bridge Hub -> Rococo Bulletin messages.
85pub type ToRococoBulletinMessagesDeliveryProof<MI> =
86	FromBridgedChainMessagesDeliveryProof<bp_polkadot_bulletin::Hash, LaneIdOf<Runtime, MI>>;
87
88/// Dispatches received XCM messages from other bridge.
89type FromRococoBulletinMessageBlobDispatcher = BridgeBlobDispatcher<
90	XcmRouter,
91	UniversalLocation,
92	BridgeRococoToRococoBulletinMessagesPalletInstance,
93>;
94
95/// Transaction extension that refunds relayers that are delivering messages from the Rococo
96/// Bulletin chain.
97pub type OnBridgeHubRococoRefundRococoBulletinMessages = BridgeRelayersTransactionExtension<
98	Runtime,
99	WithMessagesExtensionConfig<
100		StrOnBridgeHubRococoRefundRococoBulletinMessages,
101		Runtime,
102		WithRococoBulletinMessagesInstance,
103		RelayersForPermissionlessLanesInstance,
104		PriorityBoostPerMessage,
105	>,
106>;
107bp_runtime::generate_static_str_provider!(OnBridgeHubRococoRefundRococoBulletinMessages);
108
109/// Add XCM messages support for BridgeHubRococo to support Rococo->Rococo Bulletin XCM messages.
110pub type WithRococoBulletinMessagesInstance = pallet_bridge_messages::Instance4;
111impl pallet_bridge_messages::Config<WithRococoBulletinMessagesInstance> for Runtime {
112	type RuntimeEvent = RuntimeEvent;
113	type WeightInfo =
114		weights::pallet_bridge_messages_rococo_to_rococo_bulletin::WeightInfo<Runtime>;
115
116	type ThisChain = bp_bridge_hub_rococo::BridgeHubRococo;
117	type BridgedChain = bp_polkadot_bulletin::PolkadotBulletin;
118	type BridgedHeaderChain = BridgeRococoBulletinGrandpa;
119
120	type OutboundPayload = XcmAsPlainPayload;
121	type InboundPayload = XcmAsPlainPayload;
122	type LaneId = LegacyLaneId;
123
124	type DeliveryPayments = ();
125	type DeliveryConfirmationPayments = ();
126
127	type MessageDispatch = XcmOverRococoBulletin;
128	type OnMessagesDelivered = XcmOverRococoBulletin;
129}
130
131/// Add support for the export and dispatch of XCM programs.
132pub type XcmOverPolkadotBulletinInstance = pallet_xcm_bridge_hub::Instance2;
133impl pallet_xcm_bridge_hub::Config<XcmOverPolkadotBulletinInstance> for Runtime {
134	type RuntimeEvent = RuntimeEvent;
135
136	type UniversalLocation = UniversalLocation;
137	type BridgedNetwork = RococoBulletinGlobalConsensusNetworkLocation;
138	type BridgeMessagesPalletInstance = WithRococoBulletinMessagesInstance;
139
140	type MessageExportPrice = ();
141	type DestinationVersion = AlwaysV5;
142
143	type ForceOrigin = EnsureRoot<AccountId>;
144	// We don't want to allow creating bridges for this instance.
145	type OpenBridgeOrigin = EnsureNever<Location>;
146	// Converter aligned with `OpenBridgeOrigin`.
147	type BridgeOriginAccountIdConverter =
148		(ParentIsPreset<AccountId>, SiblingParachainConvertsVia<Sibling, AccountId>);
149
150	type BridgeDeposit = BridgeDeposit;
151	type Currency = Balances;
152	type RuntimeHoldReason = RuntimeHoldReason;
153	// Do not require deposit from People parachains.
154	type AllowWithoutBridgeDeposit = Equals<PeopleRococoLocation>;
155
156	type LocalXcmChannelManager = ();
157	type BlobDispatcher = FromRococoBulletinMessageBlobDispatcher;
158}
159
160#[cfg(test)]
161mod tests {
162	use super::*;
163	use crate::bridge_common_config::BridgeGrandpaRococoBulletinInstance;
164	use bridge_runtime_common::{
165		assert_complete_bridge_types, integrity::check_message_lane_weights,
166	};
167	use parachains_common::Balance;
168	use testnet_parachains_constants::rococo;
169
170	/// Every additional message in the message delivery transaction boosts its priority.
171	/// So the priority of transaction with `N+1` messages is larger than priority of
172	/// transaction with `N` messages by the `PriorityBoostPerMessage`.
173	///
174	/// Economically, it is an equivalent of adding tip to the transaction with `N` messages.
175	/// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip.
176	///
177	/// We want this tip to be large enough (delivery transactions with more messages = less
178	/// operational costs and a faster bridge), so this value should be significant.
179	const FEE_BOOST_PER_MESSAGE: Balance = 2 * rococo::currency::UNITS;
180
181	// see `FEE_BOOST_PER_MESSAGE` comment
182	const FEE_BOOST_PER_RELAY_HEADER: Balance = 2 * rococo::currency::UNITS;
183
184	#[test]
185	fn ensure_bridge_hub_rococo_message_lane_weights_are_correct() {
186		check_message_lane_weights::<
187			bp_bridge_hub_rococo::BridgeHubRococo,
188			Runtime,
189			WithRococoBulletinMessagesInstance,
190		>(
191			bp_polkadot_bulletin::EXTRA_STORAGE_PROOF_SIZE,
192			bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
193			bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
194			true,
195		);
196	}
197
198	#[test]
199	fn ensure_bridge_integrity() {
200		assert_complete_bridge_types!(
201			runtime: Runtime,
202			with_bridged_chain_messages_instance: WithRococoBulletinMessagesInstance,
203			this_chain: bp_bridge_hub_rococo::BridgeHubRococo,
204			bridged_chain: bp_polkadot_bulletin::PolkadotBulletin,
205			expected_payload_type: XcmAsPlainPayload,
206		);
207
208		// we can't use `assert_complete_bridge_constants` here, because there's a trick with
209		// Bulletin chain - it has the same (almost) runtime for Polkadot Bulletin and Rococo
210		// Bulletin, so we have to adhere Polkadot names here
211
212		pallet_bridge_relayers::extension::per_relay_header::ensure_priority_boost_is_sane::<
213			Runtime,
214			BridgeGrandpaRococoBulletinInstance,
215			PriorityBoostPerRelayHeader,
216		>(FEE_BOOST_PER_RELAY_HEADER);
217
218		pallet_bridge_relayers::extension::per_message::ensure_priority_boost_is_sane::<
219			Runtime,
220			WithRococoBulletinMessagesInstance,
221			PriorityBoostPerMessage,
222		>(FEE_BOOST_PER_MESSAGE);
223
224		let expected: InteriorLocation = PalletInstance(
225			bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_BULLETIN_MESSAGES_PALLET_INDEX,
226		)
227		.into();
228
229		assert_eq!(BridgeRococoToRococoBulletinMessagesPalletInstance::get(), expected,);
230	}
231}
232
233#[cfg(feature = "runtime-benchmarks")]
234pub(crate) fn open_bridge_for_benchmarks<R, XBHI, C>(
235	with: pallet_xcm_bridge_hub::LaneIdOf<R, XBHI>,
236	sibling_para_id: u32,
237) -> InteriorLocation
238where
239	R: pallet_xcm_bridge_hub::Config<XBHI>,
240	XBHI: 'static,
241	C: xcm_executor::traits::ConvertLocation<
242		bp_runtime::AccountIdOf<pallet_xcm_bridge_hub::ThisChainOf<R, XBHI>>,
243	>,
244{
245	use pallet_xcm_bridge_hub::{Bridge, BridgeId, BridgeState};
246	use sp_runtime::traits::Zero;
247	use xcm::{latest::ROCOCO_GENESIS_HASH, VersionedInteriorLocation};
248
249	// insert bridge metadata
250	let lane_id = with;
251	let sibling_parachain = Location::new(1, [Parachain(sibling_para_id)]);
252	let universal_source =
253		[GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), Parachain(sibling_para_id)].into();
254	let universal_destination =
255		[GlobalConsensus(RococoBulletinGlobalConsensusNetwork::get())].into();
256	let bridge_id = BridgeId::new(&universal_source, &universal_destination);
257
258	// insert only bridge metadata, because the benchmarks create lanes
259	pallet_xcm_bridge_hub::Bridges::<R, XBHI>::insert(
260		bridge_id,
261		Bridge {
262			bridge_origin_relative_location: alloc::boxed::Box::new(
263				sibling_parachain.clone().into(),
264			),
265			bridge_origin_universal_location: alloc::boxed::Box::new(
266				VersionedInteriorLocation::from(universal_source.clone()),
267			),
268			bridge_destination_universal_location: alloc::boxed::Box::new(
269				VersionedInteriorLocation::from(universal_destination),
270			),
271			state: BridgeState::Opened,
272			bridge_owner_account: C::convert_location(&sibling_parachain).expect("valid AccountId"),
273			deposit: Zero::zero(),
274			lane_id,
275		},
276	);
277	pallet_xcm_bridge_hub::LaneToBridge::<R, XBHI>::insert(lane_id, bridge_id);
278
279	universal_source
280}