//! The `pallet_xcm_bridge_hub` pallet is used to manage (open, close) bridges between chains from
//! different consensuses. The new extrinsics `fn open_bridge` and `fn close_bridge` are introduced.
//! messages. Each lane is a unique connection between two chains from different consensuses and is
//! - `bridge_origin_universal_location`, `bridge_destination_universal_location` is converted to
//! - We need the same `LaneId` on both sides of the bridge, as `LaneId` is part of the message key
//! - We already have a running production Polkadot/Kusama bridge that uses `LaneId([0, 0, 0, 0])`.
//! `LaneId` is backward compatible, meaning it can be encoded/decoded from the older format `[u8;
//! The `pallet_xcm_bridge_hub` pallet needs to store some metadata about opened bridges. The bridge
//! `bridge_origin_universal_location` using the `latest` XCM structs. `BridgeId` is not transferred
//! over the bridge; it is only important for local consensus. It essentially serves as an index/key
//! to bridge metadata. All the XCM infrastructure around `XcmExecutor`, `SendXcm`, `ExportXcm` use
//! the `latest` XCM, so `BridgeId` must remain compatible with the `latest` XCM. For example, we
//! have an `ExportXcm` implementation in `exporter.rs` that handles the `ExportMessage` instruction
//! with `universal_source` and `destination` (latest XCM), so we need to create `BridgeId` and the
//! This pallet implements `try_state`, ensuring compatibility and checking everything so we know if
//! except removing older XCM versions. In such cases, we need to add migration for `BridgeId` and
//! stored `Versioned*` structs and update `LaneToBridge` mapping, but this won't affect `LaneId`
//! origin to the XCM `Location` and converts it to the `bridge_origin_universal_location`. With the
//! `bridge_destination_universal_location`, which is the other side of the bridge from a different
//! 2) the sibling parachain funds its sovereign parachain account at this bridge hub. It shall hold
//! 4) at the other side of the bridge, the same thing (1, 2, 3) happens. Parachains that need to
//! Otherwise, the owner must repeat the `close_bridge` call to prune all queued messages first.
//! - BridgeHubPolkadot with `UniversalLocation` = `[GlobalConsensus(Polkadot), Parachain(1002)]`
//! 1. The Polkadot local sibling parachain `Location::new(1, Parachain(1234))` must send some DOTs
//! to its sovereign account on BridgeHubPolkadot to cover `BridgeDeposit`, fees for `Transact`,
//! XcmOverBridgeHubKusama::open_bridge( VersionedInteriorLocation::V4([GlobalConsensus(Kusama),
//! 4. The Kusama local sibling parachain `Location::new(1, Parachain(4567))` must send some KSMs to
//! on BridgeHubKusama to cover `BridgeDeposit`, fees for `Transact`, and the existential deposit.
//! VersionedInteriorLocation::V4([GlobalConsensus(Polkadot), Parachain(1234)].into()), ); ) ```
//! The opening bridge holds the configured `BridgeDeposit` from the origin's sovereign account, but
// `T as pallet_bridge_messages::Config<T::BridgeMessagesPalletInstance>::BridgedChain::NetworkId`
"Configured `T::BridgedNetwork`: {:?} does not contain `GlobalConsensus` junction with `NetworkId`!",
// TODO: https://github.com/paritytech/parity-bridges-common/issues/1760 - may do refund here, if
"Bridge {:?} between {:?} and {:?} has closed lane_id: {:?}, the bridge deposit {released_deposit:?} was returned",
log::info!(target: LOG_TARGET, "Checking `do_try_state_for_bridge` for bridge_id: {bridge_id:?} and bridge: {bridge:?}");
"`bridge.bridge_origin_relative_location` cannot be converted to the `latest` XCM, needs migration!"
let bridge_origin_universal_location_as_latest: &InteriorLocation = bridge.bridge_origin_universal_location
.map_err(|_| "`bridge.bridge_origin_universal_location` cannot be converted to the `latest` XCM, needs migration!")?;
let bridge_destination_universal_location_as_latest: &InteriorLocation = bridge.bridge_destination_universal_location
.map_err(|_| "`bridge.bridge_destination_universal_location` cannot be converted to the `latest` XCM, needs migration!")?;
bridge_id == BridgeId::new(bridge_origin_universal_location_as_latest, bridge_destination_universal_location_as_latest),
"`bridge_id` is different than calculated from `bridge_origin_universal_location_as_latest` and `bridge_destination_universal_location_as_latest`, needs migration!"
T::BridgeOriginAccountIdConverter::convert_location(bridge_origin_relative_location_as_latest) == Some(deposit.account),
"`bridge.deposit.account` is different than calculated from `bridge.bridge_origin_relative_location`, needs migration!"
for lane_id in pallet_bridge_messages::InboundLanes::<T, T::BridgeMessagesPalletInstance>::iter_keys() {
log::info!(target: LOG_TARGET, "Checking `do_try_state_for_messages` for `InboundLanes`'s lane_id: {lane_id:?}...");
for lane_id in pallet_bridge_messages::OutboundLanes::<T, T::BridgeMessagesPalletInstance>::iter_keys() {
log::info!(target: LOG_TARGET, "Checking `do_try_state_for_messages` for `OutboundLanes`'s lane_id: {lane_id:?}...");