diff --git a/bridges/modules/xcm-bridge-hub/README.md b/bridges/modules/xcm-bridge-hub/README.md new file mode 100644 index 0000000000000000000000000000000000000000..42bf3c18bed6a3c452e5e2b9228ae02dad88222a --- /dev/null +++ b/bridges/modules/xcm-bridge-hub/README.md @@ -0,0 +1,86 @@ +# Bridge XCM Bridge Hub Pallet + +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. Other chains can manage channels +with different bridged global consensuses. + +## Concept of `lane` and `LaneId` + +There is another `pallet_bridge_messages` pallet that handles inbound/outbound lanes for messages. +Each lane is a unique connection between two chains from different consensuses and is identified by `LaneId`. +`LaneId` is generated once when a new bridge is requested by `fn open_bridge`. +It is generated by `BridgeLocations::calculate_lane_id` based on the following parameters: +- Source `bridge_origin_universal_location` (latest XCM) +- Destination `bridge_destination_universal_location` (latest XCM) +- XCM version (both sides of the bridge must use the same parameters to generate the same `LaneId`) + - `bridge_origin_universal_location`, `bridge_destination_universal_location` is converted to the `Versioned*` structs + +`LaneId` is expected to never change because: +- We need the same `LaneId` on both sides of the bridge, as `LaneId` is part of the message key proofs. +- Runtime upgrades are entirely asynchronous. +- 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; 4]` used for +static lanes, as well as the new format `H256` generated by `BridgeLocations::calculate_lane_id`. + +## Concept of `bridge` and `BridgeId` + +The `pallet_xcm_bridge_hub` pallet needs to store some metadata about opened bridges. +The bridge (or bridge metadata) is stored under the `BridgeId` key. + +`BridgeId` is generated from `bridge_origin_relative_location` and `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 corresponding `LaneId`. + +## Migrations and State + +This pallet implements `try_state`, ensuring compatibility and checking everything so we know if any migration is needed. +`do_try_state` checks for `BridgeId` compatibility, which is recalculated on runtime upgrade. +Upgrading to a new XCM version should not break anything, 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` over the bridge. + +## How to Open a Bridge? + +The `pallet_xcm_bridge_hub` pallet has the extrinsic `fn open_bridge` and +an important configuration `pallet_xcm_bridge_hub::Config::OpenBridgeOrigin`, +which translates the call's origin to the XCM `Location` and converts it to the `bridge_origin_universal_location`. +With the current setup, this origin/location is expected to be either the relay chain or a sibling parachain +as one side of the bridge. Another parameter is `bridge_destination_universal_location`, +which is the other side of the bridge from a different global consensus. + +Example of opening a bridge between some random parachains from Polkadot and Kusama: + +1. The local sibling parachain `Location::new(1, Parachain(1234))` must send some DOTs to its sovereign account + on BridgeHubPolkadot to cover `BridgeDeposit`, fees for `Transact`, and the existential deposit. +2. Send a call to the BridgeHubPolkadot from the local sibling parachain: `Location::new(1, Parachain(1234))` + ``` + xcm::Transact( + origin_kind: OriginKind::Xcm, + XcmOverBridgeHubKusama::open_bridge( + VersionedInteriorLocation::V4([GlobalConsensus(Kusama), Parachain(4567)].into()), + ); + ) + ``` +3. Check the stored bridge metadata and generated `LaneId`. +4. The local sibling parachain `Location::new(1, Parachain(4567))` must send some KSMs to its sovereign account + on BridgeHubKusama to cover `BridgeDeposit`, fees for `Transact`, and the existential deposit. +5. Send a call to the BridgeHubKusama from the local sibling parachain: `Location::new(1, Parachain(4567))` + ``` + xcm::Transact( + origin_kind: OriginKind::Xcm, + XcmOverBridgeHubKusama::open_bridge( + VersionedInteriorLocation::V4([GlobalConsensus(Polkadot), Parachain(1234)].into()), + ); + ) + ``` +6. Check the stored bridge metadata and generated `LaneId`. +7. Run the bridge messages relayer for `LaneId`. +8. Send messages from both sides. + +The opening bridge holds the configured `BridgeDeposit` from the origin's sovereign account, +but this deposit is returned when the bridge is closed with `fn close_bridge`. \ No newline at end of file