1use crate::{
20 bridge_common_config::{
21 BridgeParachainWestendInstance, DeliveryRewardInBalance,
22 RelayersForLegacyLaneIdsMessagesInstance,
23 },
24 weights,
25 xcm_config::UniversalLocation,
26 AccountId, Balance, Balances, BridgeWestendMessages, PolkadotXcm, Runtime, RuntimeEvent,
27 RuntimeHoldReason, XcmOverBridgeHubWestend, XcmRouter, XcmpQueue,
28};
29use bp_messages::{
30 source_chain::FromBridgedChainMessagesDeliveryProof,
31 target_chain::FromBridgedChainMessagesProof, LegacyLaneId,
32};
33use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge;
34use pallet_xcm_bridge_hub::{BridgeId, XcmAsPlainPayload};
35
36use frame_support::{parameter_types, traits::PalletInfoAccess};
37use frame_system::{EnsureNever, EnsureRoot};
38use pallet_bridge_messages::LaneIdOf;
39use pallet_bridge_relayers::extension::{
40 BridgeRelayersTransactionExtension, WithMessagesExtensionConfig,
41};
42use parachains_common::xcm_config::{AllSiblingSystemParachains, RelayOrOtherSystemParachains};
43use polkadot_parachain_primitives::primitives::Sibling;
44use testnet_parachains_constants::rococo::currency::UNITS as ROC;
45use xcm::{
46 latest::{prelude::*, WESTEND_GENESIS_HASH},
47 prelude::{InteriorLocation, NetworkId},
48};
49use xcm_builder::{BridgeBlobDispatcher, ParentIsPreset, SiblingParachainConvertsVia};
50
51parameter_types! {
52 pub BridgeRococoToWestendMessagesPalletInstance: InteriorLocation = [PalletInstance(<BridgeWestendMessages as PalletInfoAccess>::index() as u8)].into();
53 pub WestendGlobalConsensusNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH);
54 pub WestendGlobalConsensusNetworkLocation: Location = Location::new(
55 2,
56 [GlobalConsensus(WestendGlobalConsensusNetwork::get())]
57 );
58 pub PriorityBoostPerRelayHeader: u64 = 32_007_814_407_814;
60 pub PriorityBoostPerParachainHeader: u64 = 1_396_340_903_540_903;
62 pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;
64
65 pub BridgeHubWestendLocation: Location = Location::new(
66 2,
67 [
68 GlobalConsensus(WestendGlobalConsensusNetwork::get()),
69 Parachain(<bp_bridge_hub_westend::BridgeHubWestend as bp_runtime::Parachain>::PARACHAIN_ID)
70 ]
71 );
72
73 pub storage BridgeDeposit: Balance = 5 * ROC;
74}
75
76pub type FromWestendBridgeHubMessagesProof<MI> =
78 FromBridgedChainMessagesProof<bp_bridge_hub_westend::Hash, LaneIdOf<Runtime, MI>>;
79pub type ToWestendBridgeHubMessagesDeliveryProof<MI> =
81 FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_westend::Hash, LaneIdOf<Runtime, MI>>;
82
83type FromWestendMessageBlobDispatcher =
85 BridgeBlobDispatcher<XcmRouter, UniversalLocation, BridgeRococoToWestendMessagesPalletInstance>;
86
87pub type OnBridgeHubRococoRefundBridgeHubWestendMessages = BridgeRelayersTransactionExtension<
90 Runtime,
91 WithMessagesExtensionConfig<
92 StrOnBridgeHubRococoRefundBridgeHubWestendMessages,
93 Runtime,
94 WithBridgeHubWestendMessagesInstance,
95 RelayersForLegacyLaneIdsMessagesInstance,
96 PriorityBoostPerMessage,
97 >,
98 LaneIdOf<Runtime, WithBridgeHubWestendMessagesInstance>,
99>;
100bp_runtime::generate_static_str_provider!(OnBridgeHubRococoRefundBridgeHubWestendMessages);
101
102pub type WithBridgeHubWestendMessagesInstance = pallet_bridge_messages::Instance3;
104impl pallet_bridge_messages::Config<WithBridgeHubWestendMessagesInstance> for Runtime {
105 type RuntimeEvent = RuntimeEvent;
106 type WeightInfo = weights::pallet_bridge_messages_rococo_to_westend::WeightInfo<Runtime>;
107
108 type ThisChain = bp_bridge_hub_rococo::BridgeHubRococo;
109 type BridgedChain = bp_bridge_hub_westend::BridgeHubWestend;
110 type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders<
111 Runtime,
112 BridgeParachainWestendInstance,
113 bp_bridge_hub_westend::BridgeHubWestend,
114 >;
115
116 type OutboundPayload = XcmAsPlainPayload;
117 type InboundPayload = XcmAsPlainPayload;
118 type LaneId = LegacyLaneId;
119
120 type DeliveryPayments = ();
121 type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
122 Runtime,
123 WithBridgeHubWestendMessagesInstance,
124 RelayersForLegacyLaneIdsMessagesInstance,
125 DeliveryRewardInBalance,
126 >;
127
128 type MessageDispatch = XcmOverBridgeHubWestend;
129 type OnMessagesDelivered = XcmOverBridgeHubWestend;
130}
131
132pub type XcmOverBridgeHubWestendInstance = pallet_xcm_bridge_hub::Instance1;
135impl pallet_xcm_bridge_hub::Config<XcmOverBridgeHubWestendInstance> for Runtime {
136 type RuntimeEvent = RuntimeEvent;
137
138 type UniversalLocation = UniversalLocation;
139 type BridgedNetwork = WestendGlobalConsensusNetworkLocation;
140 type BridgeMessagesPalletInstance = WithBridgeHubWestendMessagesInstance;
141
142 type MessageExportPrice = ();
143 type DestinationVersion =
144 XcmVersionOfDestAndRemoteBridge<PolkadotXcm, BridgeHubWestendLocation>;
145
146 type ForceOrigin = EnsureRoot<AccountId>;
147 type OpenBridgeOrigin = EnsureNever<Location>;
149 type BridgeOriginAccountIdConverter =
151 (ParentIsPreset<AccountId>, SiblingParachainConvertsVia<Sibling, AccountId>);
152
153 type BridgeDeposit = BridgeDeposit;
154 type Currency = Balances;
155 type RuntimeHoldReason = RuntimeHoldReason;
156 type AllowWithoutBridgeDeposit =
158 RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>;
159
160 type LocalXcmChannelManager = CongestionManager;
161 type BlobDispatcher = FromWestendMessageBlobDispatcher;
162}
163
164pub struct CongestionManager;
166impl pallet_xcm_bridge_hub::LocalXcmChannelManager for CongestionManager {
167 type Error = SendError;
168
169 fn is_congested(with: &Location) -> bool {
170 use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
174 cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider::<Runtime>::is_congested(
175 with,
176 )
177 }
178
179 fn suspend_bridge(local_origin: &Location, bridge: BridgeId) -> Result<(), Self::Error> {
180 send_xcm::<XcmpQueue>(
183 local_origin.clone(),
184 bp_asset_hub_rococo::build_congestion_message(bridge.inner(), true).into(),
185 )
186 .map(|_| ())
187 }
188
189 fn resume_bridge(local_origin: &Location, bridge: BridgeId) -> Result<(), Self::Error> {
190 send_xcm::<XcmpQueue>(
193 local_origin.clone(),
194 bp_asset_hub_rococo::build_congestion_message(bridge.inner(), false).into(),
195 )
196 .map(|_| ())
197 }
198}
199
200#[cfg(feature = "runtime-benchmarks")]
201pub(crate) fn open_bridge_for_benchmarks<R, XBHI, C>(
202 with: pallet_xcm_bridge_hub::LaneIdOf<R, XBHI>,
203 sibling_para_id: u32,
204) -> InteriorLocation
205where
206 R: pallet_xcm_bridge_hub::Config<XBHI>,
207 XBHI: 'static,
208 C: xcm_executor::traits::ConvertLocation<
209 bp_runtime::AccountIdOf<pallet_xcm_bridge_hub::ThisChainOf<R, XBHI>>,
210 >,
211{
212 use pallet_xcm_bridge_hub::{Bridge, BridgeId, BridgeState};
213 use sp_runtime::traits::Zero;
214 use xcm::{latest::ROCOCO_GENESIS_HASH, VersionedInteriorLocation};
215
216 let lane_id = with;
218 let sibling_parachain = Location::new(1, [Parachain(sibling_para_id)]);
219 let universal_source =
220 [GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), Parachain(sibling_para_id)].into();
221 let universal_destination =
222 [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), Parachain(2075)].into();
223 let bridge_id = BridgeId::new(&universal_source, &universal_destination);
224
225 pallet_xcm_bridge_hub::Bridges::<R, XBHI>::insert(
227 bridge_id,
228 Bridge {
229 bridge_origin_relative_location: alloc::boxed::Box::new(
230 sibling_parachain.clone().into(),
231 ),
232 bridge_origin_universal_location: alloc::boxed::Box::new(
233 VersionedInteriorLocation::from(universal_source.clone()),
234 ),
235 bridge_destination_universal_location: alloc::boxed::Box::new(
236 VersionedInteriorLocation::from(universal_destination),
237 ),
238 state: BridgeState::Opened,
239 bridge_owner_account: C::convert_location(&sibling_parachain).expect("valid AccountId"),
240 deposit: Zero::zero(),
241 lane_id,
242 },
243 );
244 pallet_xcm_bridge_hub::LaneToBridge::<R, XBHI>::insert(lane_id, bridge_id);
245
246 universal_source
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252 use crate::bridge_common_config::BridgeGrandpaWestendInstance;
253 use bridge_runtime_common::{
254 assert_complete_bridge_types,
255 integrity::{
256 assert_complete_with_parachain_bridge_constants, check_message_lane_weights,
257 AssertChainConstants, AssertCompleteBridgeConstants,
258 },
259 };
260
261 const FEE_BOOST_PER_MESSAGE: Balance = 2 * ROC;
271
272 const FEE_BOOST_PER_RELAY_HEADER: Balance = 2 * ROC;
274 const FEE_BOOST_PER_PARACHAIN_HEADER: Balance = 2 * ROC;
276
277 #[test]
278 fn ensure_bridge_hub_rococo_message_lane_weights_are_correct() {
279 check_message_lane_weights::<
280 bp_bridge_hub_rococo::BridgeHubRococo,
281 Runtime,
282 WithBridgeHubWestendMessagesInstance,
283 >(
284 bp_bridge_hub_westend::EXTRA_STORAGE_PROOF_SIZE,
285 bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
286 bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
287 true,
288 );
289 }
290
291 #[test]
292 fn ensure_bridge_integrity() {
293 assert_complete_bridge_types!(
294 runtime: Runtime,
295 with_bridged_chain_messages_instance: WithBridgeHubWestendMessagesInstance,
296 this_chain: bp_bridge_hub_rococo::BridgeHubRococo,
297 bridged_chain: bp_bridge_hub_westend::BridgeHubWestend,
298 expected_payload_type: XcmAsPlainPayload,
299 );
300
301 assert_complete_with_parachain_bridge_constants::<
302 Runtime,
303 BridgeGrandpaWestendInstance,
304 WithBridgeHubWestendMessagesInstance,
305 >(AssertCompleteBridgeConstants {
306 this_chain_constants: AssertChainConstants {
307 block_length: bp_bridge_hub_rococo::BlockLength::get(),
308 block_weights: bp_bridge_hub_rococo::BlockWeightsForAsyncBacking::get(),
309 },
310 });
311
312 pallet_bridge_relayers::extension::per_relay_header::ensure_priority_boost_is_sane::<
313 Runtime,
314 BridgeGrandpaWestendInstance,
315 PriorityBoostPerRelayHeader,
316 >(FEE_BOOST_PER_RELAY_HEADER);
317
318 pallet_bridge_relayers::extension::per_parachain_header::ensure_priority_boost_is_sane::<
319 Runtime,
320 WithBridgeHubWestendMessagesInstance,
321 bp_bridge_hub_westend::BridgeHubWestend,
322 PriorityBoostPerParachainHeader,
323 >(FEE_BOOST_PER_PARACHAIN_HEADER);
324
325 pallet_bridge_relayers::extension::per_message::ensure_priority_boost_is_sane::<
326 Runtime,
327 WithBridgeHubWestendMessagesInstance,
328 PriorityBoostPerMessage,
329 >(FEE_BOOST_PER_MESSAGE);
330
331 let expected: InteriorLocation = [PalletInstance(
332 bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX,
333 )]
334 .into();
335
336 assert_eq!(BridgeRococoToWestendMessagesPalletInstance::get(), expected,);
337 }
338}
339
340pub mod migration {
342 use super::*;
343 use frame_support::traits::ConstBool;
344
345 parameter_types! {
346 pub AssetHubRococoToAssetHubWestendMessagesLane: LegacyLaneId = LegacyLaneId([0, 0, 0, 2]);
347 pub AssetHubRococoLocation: Location = Location::new(1, [Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID)]);
348 pub AssetHubWestendUniversalLocation: InteriorLocation = [GlobalConsensus(WestendGlobalConsensusNetwork::get()), Parachain(bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID)].into();
349 }
350
351 pub type StaticToDynamicLanes = pallet_xcm_bridge_hub::migration::OpenBridgeForLane<
353 Runtime,
354 XcmOverBridgeHubWestendInstance,
355 AssetHubRococoToAssetHubWestendMessagesLane,
356 ConstBool<false>,
359 AssetHubRococoLocation,
360 AssetHubWestendUniversalLocation,
361 >;
362
363 mod v1_wrong {
364 use bp_messages::{LaneState, MessageNonce, UnrewardedRelayer};
365 use bp_runtime::AccountIdOf;
366 use codec::{Decode, Encode};
367 use pallet_bridge_messages::BridgedChainOf;
368 use sp_std::collections::vec_deque::VecDeque;
369
370 #[derive(Encode, Decode, Clone, PartialEq, Eq)]
371 pub(crate) struct StoredInboundLaneData<T: pallet_bridge_messages::Config<I>, I: 'static>(
372 pub(crate) InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
373 );
374 #[derive(Encode, Decode, Clone, PartialEq, Eq)]
375 pub(crate) struct InboundLaneData<RelayerId> {
376 pub state: LaneState,
377 pub(crate) relayers: VecDeque<UnrewardedRelayer<RelayerId>>,
378 pub(crate) last_confirmed_nonce: MessageNonce,
379 }
380 #[derive(Encode, Decode, Clone, PartialEq, Eq)]
381 pub(crate) struct OutboundLaneData {
382 pub state: LaneState,
383 pub(crate) oldest_unpruned_nonce: MessageNonce,
384 pub(crate) latest_received_nonce: MessageNonce,
385 pub(crate) latest_generated_nonce: MessageNonce,
386 }
387 }
388
389 mod v1 {
390 pub use bp_messages::{InboundLaneData, LaneState, OutboundLaneData};
391 pub use pallet_bridge_messages::{InboundLanes, OutboundLanes, StoredInboundLaneData};
392 }
393
394 pub struct FixMessagesV1Migration<T, I>(sp_std::marker::PhantomData<(T, I)>);
397
398 impl<T: pallet_bridge_messages::Config<I>, I: 'static> frame_support::traits::OnRuntimeUpgrade
399 for FixMessagesV1Migration<T, I>
400 {
401 fn on_runtime_upgrade() -> Weight {
402 use sp_core::Get;
403 let mut weight = T::DbWeight::get().reads(1);
404
405 let translate_inbound =
407 |pre: v1_wrong::StoredInboundLaneData<T, I>| -> Option<v1::StoredInboundLaneData<T, I>> {
408 weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
409 Some(v1::StoredInboundLaneData(v1::InboundLaneData {
410 state: v1::LaneState::Opened,
411 relayers: pre.0.relayers,
412 last_confirmed_nonce: pre.0.last_confirmed_nonce,
413 }))
414 };
415 v1::InboundLanes::<T, I>::translate_values(translate_inbound);
416
417 let translate_outbound =
419 |pre: v1_wrong::OutboundLaneData| -> Option<v1::OutboundLaneData> {
420 weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
421 Some(v1::OutboundLaneData {
422 state: v1::LaneState::Opened,
423 oldest_unpruned_nonce: pre.oldest_unpruned_nonce,
424 latest_received_nonce: pre.latest_received_nonce,
425 latest_generated_nonce: pre.latest_generated_nonce,
426 })
427 };
428 v1::OutboundLanes::<T, I>::translate_values(translate_outbound);
429
430 weight
431 }
432 }
433}