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 BridgeRelayersSignedExtension, 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::*,
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::Westend;
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 = BridgeRelayersSignedExtension<
89 Runtime,
90 WithMessagesExtensionConfig<
91 StrOnBridgeHubRococoRefundBridgeHubWestendMessages,
92 Runtime,
93 WithBridgeHubWestendMessagesInstance,
94 RelayersForLegacyLaneIdsMessagesInstance,
95 PriorityBoostPerMessage,
96 >,
97 LaneIdOf<Runtime, WithBridgeHubWestendMessagesInstance>,
98>;
99bp_runtime::generate_static_str_provider!(OnBridgeHubRococoRefundBridgeHubWestendMessages);
100
101pub type WithBridgeHubWestendMessagesInstance = pallet_bridge_messages::Instance3;
103impl pallet_bridge_messages::Config<WithBridgeHubWestendMessagesInstance> for Runtime {
104 type RuntimeEvent = RuntimeEvent;
105 type WeightInfo = weights::pallet_bridge_messages_rococo_to_westend::WeightInfo<Runtime>;
106
107 type ThisChain = bp_bridge_hub_rococo::BridgeHubRococo;
108 type BridgedChain = bp_bridge_hub_westend::BridgeHubWestend;
109 type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders<
110 Runtime,
111 BridgeParachainWestendInstance,
112 bp_bridge_hub_westend::BridgeHubWestend,
113 >;
114
115 type OutboundPayload = XcmAsPlainPayload;
116 type InboundPayload = XcmAsPlainPayload;
117 type LaneId = LegacyLaneId;
118
119 type DeliveryPayments = ();
120 type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
121 Runtime,
122 WithBridgeHubWestendMessagesInstance,
123 RelayersForLegacyLaneIdsMessagesInstance,
124 DeliveryRewardInBalance,
125 >;
126
127 type MessageDispatch = XcmOverBridgeHubWestend;
128 type OnMessagesDelivered = XcmOverBridgeHubWestend;
129}
130
131pub type XcmOverBridgeHubWestendInstance = pallet_xcm_bridge_hub::Instance1;
134impl pallet_xcm_bridge_hub::Config<XcmOverBridgeHubWestendInstance> for Runtime {
135 type RuntimeEvent = RuntimeEvent;
136
137 type UniversalLocation = UniversalLocation;
138 type BridgedNetwork = WestendGlobalConsensusNetworkLocation;
139 type BridgeMessagesPalletInstance = WithBridgeHubWestendMessagesInstance;
140
141 type MessageExportPrice = ();
142 type DestinationVersion =
143 XcmVersionOfDestAndRemoteBridge<PolkadotXcm, BridgeHubWestendLocation>;
144
145 type ForceOrigin = EnsureRoot<AccountId>;
146 type OpenBridgeOrigin = EnsureNever<Location>;
148 type BridgeOriginAccountIdConverter =
150 (ParentIsPreset<AccountId>, SiblingParachainConvertsVia<Sibling, AccountId>);
151
152 type BridgeDeposit = BridgeDeposit;
153 type Currency = Balances;
154 type RuntimeHoldReason = RuntimeHoldReason;
155 type AllowWithoutBridgeDeposit =
157 RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>;
158
159 type LocalXcmChannelManager = CongestionManager;
160 type BlobDispatcher = FromWestendMessageBlobDispatcher;
161}
162
163pub struct CongestionManager;
165impl pallet_xcm_bridge_hub::LocalXcmChannelManager for CongestionManager {
166 type Error = SendError;
167
168 fn is_congested(with: &Location) -> bool {
169 use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
173 cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider::<Runtime>::is_congested(
174 with,
175 )
176 }
177
178 fn suspend_bridge(local_origin: &Location, bridge: BridgeId) -> Result<(), Self::Error> {
179 send_xcm::<XcmpQueue>(
182 local_origin.clone(),
183 bp_asset_hub_rococo::build_congestion_message(bridge.inner(), true).into(),
184 )
185 .map(|_| ())
186 }
187
188 fn resume_bridge(local_origin: &Location, bridge: BridgeId) -> Result<(), Self::Error> {
189 send_xcm::<XcmpQueue>(
192 local_origin.clone(),
193 bp_asset_hub_rococo::build_congestion_message(bridge.inner(), false).into(),
194 )
195 .map(|_| ())
196 }
197}
198
199#[cfg(feature = "runtime-benchmarks")]
200pub(crate) fn open_bridge_for_benchmarks<R, XBHI, C>(
201 with: pallet_xcm_bridge_hub::LaneIdOf<R, XBHI>,
202 sibling_para_id: u32,
203) -> InteriorLocation
204where
205 R: pallet_xcm_bridge_hub::Config<XBHI>,
206 XBHI: 'static,
207 C: xcm_executor::traits::ConvertLocation<
208 bp_runtime::AccountIdOf<pallet_xcm_bridge_hub::ThisChainOf<R, XBHI>>,
209 >,
210{
211 use pallet_xcm_bridge_hub::{Bridge, BridgeState};
212 use sp_runtime::traits::Zero;
213 use xcm::VersionedInteriorLocation;
214
215 let lane_id = with;
217 let sibling_parachain = Location::new(1, [Parachain(sibling_para_id)]);
218 let universal_source = [GlobalConsensus(Rococo), Parachain(sibling_para_id)].into();
219 let universal_destination = [GlobalConsensus(Westend), Parachain(2075)].into();
220 let bridge_id = BridgeId::new(&universal_source, &universal_destination);
221
222 pallet_xcm_bridge_hub::Bridges::<R, XBHI>::insert(
224 bridge_id,
225 Bridge {
226 bridge_origin_relative_location: alloc::boxed::Box::new(
227 sibling_parachain.clone().into(),
228 ),
229 bridge_origin_universal_location: alloc::boxed::Box::new(
230 VersionedInteriorLocation::from(universal_source.clone()),
231 ),
232 bridge_destination_universal_location: alloc::boxed::Box::new(
233 VersionedInteriorLocation::from(universal_destination),
234 ),
235 state: BridgeState::Opened,
236 bridge_owner_account: C::convert_location(&sibling_parachain).expect("valid AccountId"),
237 deposit: Zero::zero(),
238 lane_id,
239 },
240 );
241 pallet_xcm_bridge_hub::LaneToBridge::<R, XBHI>::insert(lane_id, bridge_id);
242
243 universal_source
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249 use crate::bridge_common_config::BridgeGrandpaWestendInstance;
250 use bridge_runtime_common::{
251 assert_complete_bridge_types,
252 integrity::{
253 assert_complete_with_parachain_bridge_constants, check_message_lane_weights,
254 AssertChainConstants, AssertCompleteBridgeConstants,
255 },
256 };
257
258 const FEE_BOOST_PER_MESSAGE: Balance = 2 * ROC;
268
269 const FEE_BOOST_PER_RELAY_HEADER: Balance = 2 * ROC;
271 const FEE_BOOST_PER_PARACHAIN_HEADER: Balance = 2 * ROC;
273
274 #[test]
275 fn ensure_bridge_hub_rococo_message_lane_weights_are_correct() {
276 check_message_lane_weights::<
277 bp_bridge_hub_rococo::BridgeHubRococo,
278 Runtime,
279 WithBridgeHubWestendMessagesInstance,
280 >(
281 bp_bridge_hub_westend::EXTRA_STORAGE_PROOF_SIZE,
282 bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
283 bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
284 true,
285 );
286 }
287
288 #[test]
289 fn ensure_bridge_integrity() {
290 assert_complete_bridge_types!(
291 runtime: Runtime,
292 with_bridged_chain_messages_instance: WithBridgeHubWestendMessagesInstance,
293 this_chain: bp_bridge_hub_rococo::BridgeHubRococo,
294 bridged_chain: bp_bridge_hub_westend::BridgeHubWestend,
295 expected_payload_type: XcmAsPlainPayload,
296 );
297
298 assert_complete_with_parachain_bridge_constants::<
299 Runtime,
300 BridgeGrandpaWestendInstance,
301 WithBridgeHubWestendMessagesInstance,
302 >(AssertCompleteBridgeConstants {
303 this_chain_constants: AssertChainConstants {
304 block_length: bp_bridge_hub_rococo::BlockLength::get(),
305 block_weights: bp_bridge_hub_rococo::BlockWeightsForAsyncBacking::get(),
306 },
307 });
308
309 pallet_bridge_relayers::extension::per_relay_header::ensure_priority_boost_is_sane::<
310 Runtime,
311 BridgeGrandpaWestendInstance,
312 PriorityBoostPerRelayHeader,
313 >(FEE_BOOST_PER_RELAY_HEADER);
314
315 pallet_bridge_relayers::extension::per_parachain_header::ensure_priority_boost_is_sane::<
316 Runtime,
317 WithBridgeHubWestendMessagesInstance,
318 bp_bridge_hub_westend::BridgeHubWestend,
319 PriorityBoostPerParachainHeader,
320 >(FEE_BOOST_PER_PARACHAIN_HEADER);
321
322 pallet_bridge_relayers::extension::per_message::ensure_priority_boost_is_sane::<
323 Runtime,
324 WithBridgeHubWestendMessagesInstance,
325 PriorityBoostPerMessage,
326 >(FEE_BOOST_PER_MESSAGE);
327
328 let expected: InteriorLocation = [PalletInstance(
329 bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX,
330 )]
331 .into();
332
333 assert_eq!(BridgeRococoToWestendMessagesPalletInstance::get(), expected,);
334 }
335}
336
337pub mod migration {
339 use super::*;
340 use frame_support::traits::ConstBool;
341
342 parameter_types! {
343 pub AssetHubRococoToAssetHubWestendMessagesLane: LegacyLaneId = LegacyLaneId([0, 0, 0, 2]);
344 pub AssetHubRococoLocation: Location = Location::new(1, [Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID)]);
345 pub AssetHubWestendUniversalLocation: InteriorLocation = [GlobalConsensus(WestendGlobalConsensusNetwork::get()), Parachain(bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID)].into();
346 }
347
348 pub type StaticToDynamicLanes = pallet_xcm_bridge_hub::migration::OpenBridgeForLane<
350 Runtime,
351 XcmOverBridgeHubWestendInstance,
352 AssetHubRococoToAssetHubWestendMessagesLane,
353 ConstBool<false>,
356 AssetHubRococoLocation,
357 AssetHubWestendUniversalLocation,
358 >;
359
360 mod v1_wrong {
361 use bp_messages::{LaneState, MessageNonce, UnrewardedRelayer};
362 use bp_runtime::AccountIdOf;
363 use codec::{Decode, Encode};
364 use pallet_bridge_messages::BridgedChainOf;
365 use sp_std::collections::vec_deque::VecDeque;
366
367 #[derive(Encode, Decode, Clone, PartialEq, Eq)]
368 pub(crate) struct StoredInboundLaneData<T: pallet_bridge_messages::Config<I>, I: 'static>(
369 pub(crate) InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
370 );
371 #[derive(Encode, Decode, Clone, PartialEq, Eq)]
372 pub(crate) struct InboundLaneData<RelayerId> {
373 pub state: LaneState,
374 pub(crate) relayers: VecDeque<UnrewardedRelayer<RelayerId>>,
375 pub(crate) last_confirmed_nonce: MessageNonce,
376 }
377 #[derive(Encode, Decode, Clone, PartialEq, Eq)]
378 pub(crate) struct OutboundLaneData {
379 pub state: LaneState,
380 pub(crate) oldest_unpruned_nonce: MessageNonce,
381 pub(crate) latest_received_nonce: MessageNonce,
382 pub(crate) latest_generated_nonce: MessageNonce,
383 }
384 }
385
386 mod v1 {
387 pub use bp_messages::{InboundLaneData, LaneState, OutboundLaneData};
388 pub use pallet_bridge_messages::{InboundLanes, OutboundLanes, StoredInboundLaneData};
389 }
390
391 pub struct FixMessagesV1Migration<T, I>(sp_std::marker::PhantomData<(T, I)>);
394
395 impl<T: pallet_bridge_messages::Config<I>, I: 'static> frame_support::traits::OnRuntimeUpgrade
396 for FixMessagesV1Migration<T, I>
397 {
398 fn on_runtime_upgrade() -> Weight {
399 use sp_core::Get;
400 let mut weight = T::DbWeight::get().reads(1);
401
402 let translate_inbound =
404 |pre: v1_wrong::StoredInboundLaneData<T, I>| -> Option<v1::StoredInboundLaneData<T, I>> {
405 weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
406 Some(v1::StoredInboundLaneData(v1::InboundLaneData {
407 state: v1::LaneState::Opened,
408 relayers: pre.0.relayers,
409 last_confirmed_nonce: pre.0.last_confirmed_nonce,
410 }))
411 };
412 v1::InboundLanes::<T, I>::translate_values(translate_inbound);
413
414 let translate_outbound =
416 |pre: v1_wrong::OutboundLaneData| -> Option<v1::OutboundLaneData> {
417 weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
418 Some(v1::OutboundLaneData {
419 state: v1::LaneState::Opened,
420 oldest_unpruned_nonce: pre.oldest_unpruned_nonce,
421 latest_received_nonce: pre.latest_received_nonce,
422 latest_generated_nonce: pre.latest_generated_nonce,
423 })
424 };
425 v1::OutboundLanes::<T, I>::translate_values(translate_outbound);
426
427 weight
428 }
429 }
430}