use crate::{
bridge_common_config::{DeliveryRewardInBalance, RelayersForLegacyLaneIdsMessagesInstance},
weights,
xcm_config::UniversalLocation,
AccountId, Balance, Balances, BridgeRococoMessages, PolkadotXcm, Runtime, RuntimeEvent,
RuntimeHoldReason, XcmOverBridgeHubRococo, XcmRouter, XcmpQueue,
};
use bp_messages::{
source_chain::FromBridgedChainMessagesDeliveryProof,
target_chain::FromBridgedChainMessagesProof, LegacyLaneId,
};
use bp_parachains::SingleParaStoredHeaderDataBuilder;
use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge;
use pallet_xcm_bridge_hub::{BridgeId, XcmAsPlainPayload};
use frame_support::{
parameter_types,
traits::{ConstU32, PalletInfoAccess},
};
use frame_system::{EnsureNever, EnsureRoot};
use pallet_bridge_messages::LaneIdOf;
use pallet_bridge_relayers::extension::{
BridgeRelayersTransactionExtension, WithMessagesExtensionConfig,
};
use parachains_common::xcm_config::{AllSiblingSystemParachains, RelayOrOtherSystemParachains};
use polkadot_parachain_primitives::primitives::Sibling;
use testnet_parachains_constants::westend::currency::UNITS as WND;
use xcm::{
latest::{prelude::*, ROCOCO_GENESIS_HASH},
prelude::{InteriorLocation, NetworkId},
};
use xcm_builder::{BridgeBlobDispatcher, ParentIsPreset, SiblingParachainConvertsVia};
parameter_types! {
pub const RelayChainHeadersToKeep: u32 = 1024;
pub const ParachainHeadsToKeep: u32 = 64;
pub const RococoBridgeParachainPalletName: &'static str = "Paras";
pub const MaxRococoParaHeadDataSize: u32 = bp_rococo::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE;
pub BridgeWestendToRococoMessagesPalletInstance: InteriorLocation = [PalletInstance(<BridgeRococoMessages as PalletInfoAccess>::index() as u8)].into();
pub RococoGlobalConsensusNetwork: NetworkId = NetworkId::ByGenesis(ROCOCO_GENESIS_HASH);
pub RococoGlobalConsensusNetworkLocation: Location = Location::new(
2,
[GlobalConsensus(RococoGlobalConsensusNetwork::get())]
);
pub PriorityBoostPerRelayHeader: u64 = 32_007_814_407_814;
pub PriorityBoostPerParachainHeader: u64 = 1_396_340_903_540_903;
pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;
pub BridgeHubRococoLocation: Location = Location::new(
2,
[
GlobalConsensus(RococoGlobalConsensusNetwork::get()),
Parachain(<bp_bridge_hub_rococo::BridgeHubRococo as bp_runtime::Parachain>::PARACHAIN_ID)
]
);
pub storage BridgeDeposit: Balance = 10 * WND;
}
pub type FromRococoBridgeHubMessagesProof<MI> =
FromBridgedChainMessagesProof<bp_bridge_hub_rococo::Hash, LaneIdOf<Runtime, MI>>;
pub type ToRococoBridgeHubMessagesDeliveryProof<MI> =
FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_rococo::Hash, LaneIdOf<Runtime, MI>>;
type FromRococoMessageBlobDispatcher =
BridgeBlobDispatcher<XcmRouter, UniversalLocation, BridgeWestendToRococoMessagesPalletInstance>;
pub type OnBridgeHubWestendRefundBridgeHubRococoMessages = BridgeRelayersTransactionExtension<
Runtime,
WithMessagesExtensionConfig<
StrOnBridgeHubWestendRefundBridgeHubRococoMessages,
Runtime,
WithBridgeHubRococoMessagesInstance,
RelayersForLegacyLaneIdsMessagesInstance,
PriorityBoostPerMessage,
>,
LaneIdOf<Runtime, WithBridgeHubRococoMessagesInstance>,
>;
bp_runtime::generate_static_str_provider!(OnBridgeHubWestendRefundBridgeHubRococoMessages);
pub type BridgeGrandpaRococoInstance = pallet_bridge_grandpa::Instance1;
impl pallet_bridge_grandpa::Config<BridgeGrandpaRococoInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type BridgedChain = bp_rococo::Rococo;
type MaxFreeHeadersPerBlock = ConstU32<4>;
type FreeHeadersInterval = ConstU32<5>;
type HeadersToKeep = RelayChainHeadersToKeep;
type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo<Runtime>;
}
pub type BridgeParachainRococoInstance = pallet_bridge_parachains::Instance1;
impl pallet_bridge_parachains::Config<BridgeParachainRococoInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = weights::pallet_bridge_parachains::WeightInfo<Runtime>;
type BridgesGrandpaPalletInstance = BridgeGrandpaRococoInstance;
type ParasPalletName = RococoBridgeParachainPalletName;
type ParaStoredHeaderDataBuilder =
SingleParaStoredHeaderDataBuilder<bp_bridge_hub_rococo::BridgeHubRococo>;
type HeadsToKeep = ParachainHeadsToKeep;
type MaxParaHeadDataSize = MaxRococoParaHeadDataSize;
}
pub type WithBridgeHubRococoMessagesInstance = pallet_bridge_messages::Instance1;
impl pallet_bridge_messages::Config<WithBridgeHubRococoMessagesInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = weights::pallet_bridge_messages::WeightInfo<Runtime>;
type ThisChain = bp_bridge_hub_westend::BridgeHubWestend;
type BridgedChain = bp_bridge_hub_rococo::BridgeHubRococo;
type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders<
Runtime,
BridgeParachainRococoInstance,
bp_bridge_hub_rococo::BridgeHubRococo,
>;
type OutboundPayload = XcmAsPlainPayload;
type InboundPayload = XcmAsPlainPayload;
type LaneId = LegacyLaneId;
type DeliveryPayments = ();
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
Runtime,
WithBridgeHubRococoMessagesInstance,
RelayersForLegacyLaneIdsMessagesInstance,
DeliveryRewardInBalance,
>;
type MessageDispatch = XcmOverBridgeHubRococo;
type OnMessagesDelivered = XcmOverBridgeHubRococo;
}
pub type XcmOverBridgeHubRococoInstance = pallet_xcm_bridge_hub::Instance1;
impl pallet_xcm_bridge_hub::Config<XcmOverBridgeHubRococoInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type UniversalLocation = UniversalLocation;
type BridgedNetwork = RococoGlobalConsensusNetworkLocation;
type BridgeMessagesPalletInstance = WithBridgeHubRococoMessagesInstance;
type MessageExportPrice = ();
type DestinationVersion = XcmVersionOfDestAndRemoteBridge<PolkadotXcm, BridgeHubRococoLocation>;
type ForceOrigin = EnsureRoot<AccountId>;
type OpenBridgeOrigin = EnsureNever<Location>;
type BridgeOriginAccountIdConverter =
(ParentIsPreset<AccountId>, SiblingParachainConvertsVia<Sibling, AccountId>);
type BridgeDeposit = BridgeDeposit;
type Currency = Balances;
type RuntimeHoldReason = RuntimeHoldReason;
type AllowWithoutBridgeDeposit =
RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>;
type LocalXcmChannelManager = CongestionManager;
type BlobDispatcher = FromRococoMessageBlobDispatcher;
}
pub struct CongestionManager;
impl pallet_xcm_bridge_hub::LocalXcmChannelManager for CongestionManager {
type Error = SendError;
fn is_congested(with: &Location) -> bool {
use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider::<Runtime>::is_congested(
with,
)
}
fn suspend_bridge(local_origin: &Location, bridge: BridgeId) -> Result<(), Self::Error> {
send_xcm::<XcmpQueue>(
local_origin.clone(),
bp_asset_hub_westend::build_congestion_message(bridge.inner(), true).into(),
)
.map(|_| ())
}
fn resume_bridge(local_origin: &Location, bridge: BridgeId) -> Result<(), Self::Error> {
send_xcm::<XcmpQueue>(
local_origin.clone(),
bp_asset_hub_westend::build_congestion_message(bridge.inner(), false).into(),
)
.map(|_| ())
}
}
#[cfg(feature = "runtime-benchmarks")]
pub(crate) fn open_bridge_for_benchmarks<R, XBHI, C>(
with: pallet_xcm_bridge_hub::LaneIdOf<R, XBHI>,
sibling_para_id: u32,
) -> InteriorLocation
where
R: pallet_xcm_bridge_hub::Config<XBHI>,
XBHI: 'static,
C: xcm_executor::traits::ConvertLocation<
bp_runtime::AccountIdOf<pallet_xcm_bridge_hub::ThisChainOf<R, XBHI>>,
>,
{
use pallet_xcm_bridge_hub::{Bridge, BridgeId, BridgeState};
use sp_runtime::traits::Zero;
use xcm::{latest::WESTEND_GENESIS_HASH, VersionedInteriorLocation};
let lane_id = with;
let sibling_parachain = Location::new(1, [Parachain(sibling_para_id)]);
let universal_source =
[GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), Parachain(sibling_para_id)].into();
let universal_destination =
[GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), Parachain(2075)].into();
let bridge_id = BridgeId::new(&universal_source, &universal_destination);
pallet_xcm_bridge_hub::Bridges::<R, XBHI>::insert(
bridge_id,
Bridge {
bridge_origin_relative_location: alloc::boxed::Box::new(
sibling_parachain.clone().into(),
),
bridge_origin_universal_location: alloc::boxed::Box::new(
VersionedInteriorLocation::from(universal_source.clone()),
),
bridge_destination_universal_location: alloc::boxed::Box::new(
VersionedInteriorLocation::from(universal_destination),
),
state: BridgeState::Opened,
bridge_owner_account: C::convert_location(&sibling_parachain).expect("valid AccountId"),
deposit: Zero::zero(),
lane_id,
},
);
pallet_xcm_bridge_hub::LaneToBridge::<R, XBHI>::insert(lane_id, bridge_id);
universal_source
}
#[cfg(test)]
mod tests {
use super::*;
use bridge_runtime_common::{
assert_complete_bridge_types,
integrity::{
assert_complete_with_parachain_bridge_constants, check_message_lane_weights,
AssertChainConstants, AssertCompleteBridgeConstants,
},
};
const FEE_BOOST_PER_MESSAGE: Balance = 2 * WND;
const FEE_BOOST_PER_RELAY_HEADER: Balance = 2 * WND;
const FEE_BOOST_PER_PARACHAIN_HEADER: Balance = 2 * WND;
#[test]
fn ensure_bridge_hub_westend_message_lane_weights_are_correct() {
check_message_lane_weights::<
bp_bridge_hub_westend::BridgeHubWestend,
Runtime,
WithBridgeHubRococoMessagesInstance,
>(
bp_bridge_hub_rococo::EXTRA_STORAGE_PROOF_SIZE,
bp_bridge_hub_westend::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
true,
);
}
#[test]
fn ensure_bridge_integrity() {
assert_complete_bridge_types!(
runtime: Runtime,
with_bridged_chain_messages_instance: WithBridgeHubRococoMessagesInstance,
this_chain: bp_bridge_hub_westend::BridgeHubWestend,
bridged_chain: bp_bridge_hub_rococo::BridgeHubRococo,
);
assert_complete_with_parachain_bridge_constants::<
Runtime,
BridgeGrandpaRococoInstance,
WithBridgeHubRococoMessagesInstance,
>(AssertCompleteBridgeConstants {
this_chain_constants: AssertChainConstants {
block_length: bp_bridge_hub_westend::BlockLength::get(),
block_weights: bp_bridge_hub_westend::BlockWeightsForAsyncBacking::get(),
},
});
pallet_bridge_relayers::extension::per_relay_header::ensure_priority_boost_is_sane::<
Runtime,
BridgeGrandpaRococoInstance,
PriorityBoostPerRelayHeader,
>(FEE_BOOST_PER_RELAY_HEADER);
pallet_bridge_relayers::extension::per_parachain_header::ensure_priority_boost_is_sane::<
Runtime,
WithBridgeHubRococoMessagesInstance,
bp_bridge_hub_rococo::BridgeHubRococo,
PriorityBoostPerParachainHeader,
>(FEE_BOOST_PER_PARACHAIN_HEADER);
pallet_bridge_relayers::extension::per_message::ensure_priority_boost_is_sane::<
Runtime,
WithBridgeHubRococoMessagesInstance,
PriorityBoostPerMessage,
>(FEE_BOOST_PER_MESSAGE);
assert_eq!(
BridgeWestendToRococoMessagesPalletInstance::get(),
[PalletInstance(
bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX
)]
);
}
}
pub mod migration {
use super::*;
use bp_messages::LegacyLaneId;
parameter_types! {
pub AssetHubWestendToAssetHubRococoMessagesLane: LegacyLaneId = LegacyLaneId([0, 0, 0, 2]);
pub AssetHubWestendLocation: Location = Location::new(1, [Parachain(bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID)]);
pub AssetHubRococoUniversalLocation: InteriorLocation = [GlobalConsensus(RococoGlobalConsensusNetwork::get()), Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID)].into();
}
mod v1_wrong {
use bp_messages::{LaneState, MessageNonce, UnrewardedRelayer};
use bp_runtime::AccountIdOf;
use codec::{Decode, Encode};
use pallet_bridge_messages::BridgedChainOf;
use sp_std::collections::vec_deque::VecDeque;
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct StoredInboundLaneData<T: pallet_bridge_messages::Config<I>, I: 'static>(
pub(crate) InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
);
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct InboundLaneData<RelayerId> {
pub state: LaneState,
pub(crate) relayers: VecDeque<UnrewardedRelayer<RelayerId>>,
pub(crate) last_confirmed_nonce: MessageNonce,
}
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct OutboundLaneData {
pub state: LaneState,
pub(crate) oldest_unpruned_nonce: MessageNonce,
pub(crate) latest_received_nonce: MessageNonce,
pub(crate) latest_generated_nonce: MessageNonce,
}
}
mod v1 {
pub use bp_messages::{InboundLaneData, LaneState, OutboundLaneData};
pub use pallet_bridge_messages::{InboundLanes, OutboundLanes, StoredInboundLaneData};
}
pub struct FixMessagesV1Migration<T, I>(sp_std::marker::PhantomData<(T, I)>);
impl<T: pallet_bridge_messages::Config<I>, I: 'static> frame_support::traits::OnRuntimeUpgrade
for FixMessagesV1Migration<T, I>
{
fn on_runtime_upgrade() -> Weight {
use sp_core::Get;
let mut weight = T::DbWeight::get().reads(1);
let translate_inbound =
|pre: v1_wrong::StoredInboundLaneData<T, I>| -> Option<v1::StoredInboundLaneData<T, I>> {
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
Some(v1::StoredInboundLaneData(v1::InboundLaneData {
state: v1::LaneState::Opened,
relayers: pre.0.relayers,
last_confirmed_nonce: pre.0.last_confirmed_nonce,
}))
};
v1::InboundLanes::<T, I>::translate_values(translate_inbound);
let translate_outbound =
|pre: v1_wrong::OutboundLaneData| -> Option<v1::OutboundLaneData> {
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
Some(v1::OutboundLaneData {
state: v1::LaneState::Opened,
oldest_unpruned_nonce: pre.oldest_unpruned_nonce,
latest_received_nonce: pre.latest_received_nonce,
latest_generated_nonce: pre.latest_generated_nonce,
})
};
v1::OutboundLanes::<T, I>::translate_values(translate_outbound);
weight
}
}
}