Skip to content
Snippets Groups Projects
Unverified Commit 149b0ac2 authored by Branislav Kontur's avatar Branislav Kontur
Browse files

Moved README.md to the lib.rs

parent c01cc8d7
Branches
No related merge requests found
Pipeline #487028 waiting for manual action with stages
in 35 minutes and 11 seconds
# 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
......@@ -18,6 +18,67 @@
//! open and close bridges between local (to this pallet location) and remote XCM
//! destinations.
//!
//! 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.
//!
//! Every bridge between two XCM locations has a dedicated lane in associated
//! messages pallet. Assuming that this pallet is deployed at the bridge hub
//! parachain and there's a similar pallet at the bridged network, the dynamic
......@@ -47,6 +108,32 @@
//! are delivered to the destination, are processed in the way their sender expects. So if we
//! can't guarantee that, we shall not care about more complex procedures and leave it to the
//! participating parties.
//!
//! # Example
//!
//! 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`.
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment