# Bridges: Permissionless Lanes **TLDR:** We are introducing a new "permissionless lanes" feature, which allows for the dynamic management of opening and closing lanes instead of the current method of hard-coding them in the source code. ## Current State of the Polkadot/Kusama Bridge The existing Polkadot/Kusama (P/K) bridge deployment involves deploying several bridge-related pallets on both BridgeHubs. - `pallet-bridge-grandpa` (for syncing GRANDPA finality, e.g., BHP follows Kusama finality, and BHK follows Polkadot finality) - `pallet-bridge-parachains` (for syncing parachain finality on the opposite BridgeHub) - `pallet-bridge-messages` (for syncing messages with the bridged side) - `pallet-xcm-bridge-hub` (acts as an XCM exporter for bridged consensus and an XCM dispatcher/router for incoming bridged messages) - `pallet-bridge-relayers` (for registering relayers and collecting rewards) The currently deployed `pallet-bridge-messages::<Instance1>` only supports the `LaneId` format `[u8; 4]`, and it has a single hard-coded lane `[0, 0, 0, 1]` for bridging Polkadot and Kusama AssetHubs. ![image](https://hackmd.io/_uploads/SySlI1Ek1e.png) ## Permissionless Lanes Feature This feature allows approved origins (relay chains, sibling parachains) to dynamically open and close bridges (via BridgeHubs) with another bridged (substrate-like) consensus, using only `xcm::Transact` and `OriginKind::Xcm`. The `pallet-xcm-bridge-hub` will manage (open and close) bridges between chains with different consensuses. The new extrinsics, `fn open_bridge` and `fn close_bridge`, facilitate this. Internally, these create or remove inbound and outbound lanes in the `pallet-bridge-messages` instance. Each lane represents a unique connection between two chains with different consensuses and is identified by a `LaneId`. A `LaneId` is generated when a new bridge is requested via `fn open_bridge`. It’s essential to ensure the same `LaneId` on both sides of the bridge, as the relayer can only relay messages when the `LaneId` matches on both ends. To achieve this, we introduced a new `LaneId` type, [`HashedLaneId`](https://github.com/paritytech/polkadot-sdk/blob/8279d1046cca51a317dec15df5a9b29240545163/bridges/primitives/messages/src/lane.rs#L102-L135), which is calculated based on the following parameters: - Source: `bridge_origin_universal_location` (from the latest XCM) - Destination: `bridge_destination_universal_location` (from the latest XCM) - XCM version (both sides of the bridge must use the same parameters to generate an identical `LaneId`) The core concept involves ordering the source and destination universal locations and then calculating a hash (`H256`). The universal location is a `xcm::InteriorLocation` that must start with `GlobalConsensus(NetworkId)`. The source universal location is derived from the origin that calls the `open_bridge` extrinsic. This algorithm ensures the same `LaneId` on both sides of the bridge. We introduced the new 32-byte `H256` `HashedLaneId` for several reasons. First, the 4-byte `[u8; 4]` format could not reliably hold the new calculated hash without conflicts. Second, upgrading the Polkadot/Kusama BridgeHubs is asynchronous, making it difficult to migrate existing `pallet-bridge-messages` to the new `HashedLaneId`. Since `LaneId` is part of the message proofs, upgrading only Kusama BridgeHub to the new `HashedLaneId` would prevent the un-upgraded Polkadot BridgeHub from understanding incoming messages. The solution is to deploy a new `pallet-bridge-messages::<Instance2>` dedicated to permissionless lanes using `LaneId(H256)`, while retaining `pallet-bridge-messages::<Instance1>` with `LaneId([u8; 4])` for AssetHubs. This approach also allows for the potential removal of `Instance1` in the future, leaving only `Instance2`. # Deployment Plan We need to deploy additional instances of the following pallets: - `pallet-bridge-messages::<Instance2>` (for syncing permissionless lane messages with `HashedLaneId`) - `pallet-xcm-bridge-hub::<Instance2>` (as a dedicated XCM exporter/dispatcher for these bridged messages) - `pallet-bridge-relayers::<Instance2>` (for registering relayers and collecting rewards) We are considering two possible variants for this deployment. ## Deployment on the BridgeHubs - Deploy the specified pallets on the BridgeHub. - Parachains (either sibling chains or AssetHub) can open a channel via XCM on both sides using `Transact(pallet-xcm-bridge-hub::<Instance2>::Call::open_bridge(..))` -> which generates a `lane_id`. - A relayer needs to be set up to relay messages for the new `lane_id`. - AssetHub still needs to send HRMP messages with `ExportXcm` to the BridgeHub. - Other parachains also need to send HRMP messages with `ExportXcm` to the BridgeHub. **Pros:** - Easier setup, as we only need to add new instances on the BridgeHubs. **Cons:** - Still requires one extra hop (through the BridgeHub) for the AssetHub scenario. - BridgeHubs only recognize the native tokens (DOT or KSM), which can be used exclusively for rewards and delivery fees. ![image](https://hackmd.io/_uploads/rJVQLJ4J1l.png) ## Deployment on the AssetHubs - Deploy the specified pallets on the AssetHub. - Parachains (sibling chains or AssetHub) can open a channel via XCM on both sides using `Transact(pallet-xcm-bridge-hub::<Instance2>::Call::open_bridge(..))`, which generates a `lane_id`. - A relayer needs to be set up to relay messages for the new `lane_id`. - AssetHub **does not need** to send HRMP messages; instead, it can directly execute `ExportXcm`, eliminating the extra hop. - Other parachains need to send HRMP messages with `ExportXcm` to the AssetHub, but this provides more options for paying fees. **Pros:** - No extra hop needed for AssetHubs, allowing direct message export. - Lower bridge fees for the sender, since the extra hop is avoided. - "Any" asset can be used for delivery fees or rewards on the AssetHubs. **Cons:** - We need to sync finality proofs (bridged `header_hash` and `state_root`) from the BridgeHub to the AssetHub, so `pallet-bridge-messages::<Instance2>` can verify received bridged messages. ![image](https://hackmd.io/_uploads/Bkxj81EJkx.png) ### Subscribe/Query/Sync Service for Finality Proofs The basic idea is that the `pallet-bridge-messages` must validate received proofs from the bridged chain, which requires a verified/proven `bridged_header_hash` and `state_root` from finality pallets. However, we don’t want to deploy finality pallets everywhere. Currently, this information is verified and stored in the `pallet-bridge-parachains`'s [`ImportedParaHeads`](https://github.com/paritytech/polkadot-sdk/blob/c77095f51119d2eccdc54d2f3518bed0ffbd6d53/bridges/modules/parachains/src/lib.rs#L288-L299) **deployed** on the **BridgeHubs**. Essentially, we need a solution that **propagates (makes available)** this information (`bridged_header_hash` and `state_root`) to the (para)chain where we want to deploy `pallet-bridge-messages`. This parachain could trigger a call on the BridgeHub's `pallet-bridge-parachains` to subscribe for new verified bridged data (`bridged_header_hash` and `state_root`). This data would then be made available to the parachain (e.g., the BridgeHub would send it via XCM using `Transact(update_proofs(bridged_header_hash, state_root))`, and the parachain would deploy a simple pallet to store this data). For more possible solutions, see: [GitHub Issue #5827](https://github.com/paritytech/polkadot-sdk/issues/5827). ## Removing the Old `pallet-bridge-messages::<Instance1>` Regardless of where `pallet-bridge-messages::<Instance2>` is deployed for permissionless lanes, we plan to remove the old instance and migrate everything to the new one. The goal is to end up with a single `pallet-bridge-messages` instance. Here are the steps to proceed: 1. Open a permissionless lane for AssetHubs in the new instance, `pallet-bridge-messages::<Instance2>`, generating a new calculated `LaneId(H256)`. 2. Once the lane is created on both sides: - We will launch new relayers (or modify existing ones). - We will start changing XCM routing on AssetHubs to use the new `pallet-xcm-bridge-hub::<Instance2>` as the XCM exporter. - This ensures no more messages will be generated for the old `pallet-bridge-messages::<Instance1>`. 3. Once the XCM routing is changed on both AssetHubs and there are no in-flight messages, we can disable dispatch or remove the old `pallet-bridge-messages::<Instance1>` from the BridgeHub. 4. Lastly, we will migrate or transfer any remaining rewards from the old `pallet-bridge-relayers::<Instance1>`. - If all rewards have been claimed, we can safely remove it.