mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 07:31:02 +00:00
* Add markdown linting
- add linter default rules
- adapt rules to current code
- fix the code for linting to pass
- add CI check
fix #1243
* Fix markdown for Substrate
* Fix tooling install
* Fix workflow
* Add documentation
* Remove trailing spaces
* Update .github/.markdownlint.yaml
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
* Fix mangled markdown/lists
* Fix captalization issues on known words
(cherry picked from commit a30092ab42)
Co-authored-by: Chevdor <chevdor@users.noreply.github.com>
This commit is contained in:
committed by
Bastian Köcher
parent
2c26640ac3
commit
91e5fc1e6d
@@ -34,9 +34,9 @@ of preference. We see that blockchains are naturally community platforms with u
|
|||||||
ultimate decision makers. We assert that good software will maximise user agency by facilitate
|
ultimate decision makers. We assert that good software will maximise user agency by facilitate
|
||||||
user-expression on the network. As such:
|
user-expression on the network. As such:
|
||||||
|
|
||||||
- This project will strive to give users as much choice as is both reasonable and possible over what
|
* This project will strive to give users as much choice as is both reasonable and possible over what
|
||||||
protocol they adhere to; but
|
protocol they adhere to; but
|
||||||
- use of the project's technical forums, commenting systems, pull requests and issue trackers as a
|
* use of the project's technical forums, commenting systems, pull requests and issue trackers as a
|
||||||
means to express individual protocol preferences is forbidden.
|
means to express individual protocol preferences is forbidden.
|
||||||
|
|
||||||
## Our Responsibilities
|
## Our Responsibilities
|
||||||
|
|||||||
+58
-60
@@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
This is a collection of components for building bridges.
|
This is a collection of components for building bridges.
|
||||||
|
|
||||||
These components include Substrate pallets for syncing headers, passing arbitrary messages, as well
|
These components include Substrate pallets for syncing headers, passing arbitrary messages, as well as libraries for
|
||||||
as libraries for building relayers to provide cross-chain communication capabilities.
|
building relayers to provide cross-chain communication capabilities.
|
||||||
|
|
||||||
Three bridge nodes are also available. The nodes can be used to run test networks which bridge other
|
Three bridge nodes are also available. The nodes can be used to run test networks which bridge other Substrate chains.
|
||||||
Substrate chains.
|
|
||||||
|
|
||||||
🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧
|
🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧
|
||||||
|
|
||||||
@@ -21,8 +20,8 @@ Substrate chains.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web
|
To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web Assembly (WASM)
|
||||||
Assembly (WASM) runtime for the node. You can configure the WASM support as so:
|
runtime for the node. You can configure the WASM support as so:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rustup install nightly
|
rustup install nightly
|
||||||
@@ -38,8 +37,8 @@ cargo build --all
|
|||||||
cargo test --all
|
cargo test --all
|
||||||
```
|
```
|
||||||
|
|
||||||
Also you can build the repo with
|
Also you can build the repo with [Parity CI Docker
|
||||||
[Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci):
|
image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker pull paritytech/bridges-ci:production
|
docker pull paritytech/bridges-ci:production
|
||||||
@@ -57,16 +56,14 @@ docker run --rm -it -w /shellhere/parity-bridges-common \
|
|||||||
If you want to reproduce other steps of CI process you can use the following
|
If you want to reproduce other steps of CI process you can use the following
|
||||||
[guide](https://github.com/paritytech/scripts#reproduce-ci-locally).
|
[guide](https://github.com/paritytech/scripts#reproduce-ci-locally).
|
||||||
|
|
||||||
If you need more information about setting up your development environment [Substrate's
|
If you need more information about setting up your development environment [Substrate's Installation
|
||||||
Installation page](https://docs.substrate.io/main-docs/install/) is a good
|
page](https://docs.substrate.io/main-docs/install/) is a good resource.
|
||||||
resource.
|
|
||||||
|
|
||||||
## High-Level Architecture
|
## High-Level Architecture
|
||||||
|
|
||||||
This repo has support for bridging foreign chains together using a combination of Substrate pallets
|
This repo has support for bridging foreign chains together using a combination of Substrate pallets and external
|
||||||
and external processes called relayers. A bridge chain is one that is able to follow the consensus
|
processes called relayers. A bridge chain is one that is able to follow the consensus of a foreign chain independently.
|
||||||
of a foreign chain independently. For example, consider the case below where we want to bridge two
|
For example, consider the case below where we want to bridge two Substrate based chains.
|
||||||
Substrate based chains.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
+---------------+ +---------------+
|
+---------------+ +---------------+
|
||||||
@@ -82,19 +79,19 @@ Substrate based chains.
|
|||||||
+---------------+
|
+---------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by
|
The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by using a runtime
|
||||||
using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact
|
module designed to track GRANDPA finality. Since two blockchains can't interact directly they need an external service,
|
||||||
directly they need an external service, called a relayer, to communicate. The relayer will subscribe
|
called a relayer, to communicate. The relayer will subscribe to new Rialto headers via RPC and submit them to the Millau
|
||||||
to new Rialto headers via RPC and submit them to the Millau chain for verification.
|
chain for verification.
|
||||||
|
|
||||||
Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth
|
Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth description of the
|
||||||
description of the bridge interaction.
|
bridge interaction.
|
||||||
|
|
||||||
## Project Layout
|
## Project Layout
|
||||||
|
|
||||||
Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual
|
Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual "blockchain", the
|
||||||
"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and
|
`modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass
|
||||||
the `relays` which are used to pass messages between chains.
|
messages between chains.
|
||||||
|
|
||||||
```
|
```
|
||||||
├── bin // Node and Runtime for the various Substrate chains
|
├── bin // Node and Runtime for the various Substrate chains
|
||||||
@@ -117,16 +114,16 @@ the `relays` which are used to pass messages between chains.
|
|||||||
|
|
||||||
## Running the Bridge
|
## Running the Bridge
|
||||||
|
|
||||||
To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes
|
To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes on each side of the
|
||||||
on each side of the bridge (source and target chain).
|
bridge (source and target chain).
|
||||||
|
|
||||||
There are 2 ways to run the bridge, described below:
|
There are 2 ways to run the bridge, described below:
|
||||||
|
|
||||||
- building & running from source: with this option, you'll be able to run the bridge between two standalone
|
- building & running from source: with this option, you'll be able to run the bridge between two standalone chains that
|
||||||
chains that are running GRANDPA finality gadget to achieve finality;
|
are running GRANDPA finality gadget to achieve finality;
|
||||||
|
|
||||||
- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains,
|
- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, complex relays
|
||||||
complex relays and more.
|
and more.
|
||||||
|
|
||||||
### Using the Source
|
### Using the Source
|
||||||
|
|
||||||
@@ -141,16 +138,15 @@ cargo build -p substrate-relay
|
|||||||
|
|
||||||
### Running a Dev network
|
### Running a Dev network
|
||||||
|
|
||||||
We will launch a dev network to demonstrate how to relay a message between two Substrate based
|
We will launch a dev network to demonstrate how to relay a message between two Substrate based chains (named Rialto and
|
||||||
chains (named Rialto and Millau).
|
Millau).
|
||||||
|
|
||||||
To do this we will need two nodes, two relayers which will relay headers, and two relayers which
|
To do this we will need two nodes, two relayers which will relay headers, and two relayers which will relay messages.
|
||||||
will relay messages.
|
|
||||||
|
|
||||||
#### Running from local scripts
|
#### Running from local scripts
|
||||||
|
|
||||||
To run a simple dev network you can use the scripts located in the
|
To run a simple dev network you can use the scripts located in the [`deployments/local-scripts`
|
||||||
[`deployments/local-scripts` folder](./deployments/local-scripts).
|
folder](./deployments/local-scripts).
|
||||||
|
|
||||||
First, we must run the two Substrate nodes.
|
First, we must run the two Substrate nodes.
|
||||||
|
|
||||||
@@ -167,8 +163,8 @@ After the nodes are up we can run the header relayers.
|
|||||||
./deployments/local-scripts/relay-rialto-to-millau.sh
|
./deployments/local-scripts/relay-rialto-to-millau.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
At this point you should see the relayer submitting headers from the Millau Substrate chain to the
|
At this point you should see the relayer submitting headers from the Millau Substrate chain to the Rialto Substrate
|
||||||
Rialto Substrate chain.
|
chain.
|
||||||
|
|
||||||
```
|
```
|
||||||
# Header Relayer Logs
|
# Header Relayer Logs
|
||||||
@@ -192,20 +188,23 @@ You will also see the message lane relayers listening for new messages.
|
|||||||
[Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces
|
[Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces
|
||||||
[...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race
|
[...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race
|
||||||
[...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces
|
[...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces
|
||||||
[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () }
|
[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces {
|
||||||
|
latest_nonce: 0, nonces_data: () }
|
||||||
[...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces
|
[...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces
|
||||||
[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () }
|
[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces {
|
||||||
|
latest_nonce: 0, nonces_data: () }
|
||||||
[...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) }
|
[...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) }
|
||||||
[...] [date] DEBUG bridge Asking Millau node about its state
|
[...] [date] DEBUG bridge Asking Millau node about its state
|
||||||
[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) }
|
[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self:
|
||||||
|
HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) }
|
||||||
```
|
```
|
||||||
|
|
||||||
To send a message see the ["How to send a message" section](#how-to-send-a-message).
|
To send a message see the ["How to send a message" section](#how-to-send-a-message).
|
||||||
|
|
||||||
### How to send a message
|
### How to send a message
|
||||||
|
|
||||||
In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM
|
In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM `Trap(43)`
|
||||||
`Trap(43)` message.
|
message.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# In `parity-bridges-common` folder
|
# In `parity-bridges-common` folder
|
||||||
@@ -222,20 +221,20 @@ TRACE bridge Sent transaction to Millau node: 0x5e68...
|
|||||||
And at the Rialto node logs you'll something like this:
|
And at the Rialto node logs you'll something like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: 48559)/Weight(ref_time: 1215065371, proof_size: 54703).
|
... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size:
|
||||||
```
|
48559)/Weight(ref_time: 1215065371, proof_size: 54703).
|
||||||
|
```
|
||||||
|
|
||||||
It means that the message has been delivered and dispatched. Message may be dispatched with an
|
It means that the message has been delivered and dispatched. Message may be dispatched with an error, though - the goal
|
||||||
error, though - the goal of our test bridge is to ensure that messages are successfully delivered
|
of our test bridge is to ensure that messages are successfully delivered and all involved components are working.
|
||||||
and all involved components are working.
|
|
||||||
|
|
||||||
## Full Network Docker Compose Setup
|
## Full Network Docker Compose Setup
|
||||||
|
|
||||||
For a more sophisticated deployment which includes bidirectional header sync, message passing,
|
For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards,
|
||||||
monitoring dashboards, etc. see the [Deployments README](./deployments/README.md).
|
etc. see the [Deployments README](./deployments/README.md).
|
||||||
|
|
||||||
You should note that you can find images for all the bridge components published on
|
You should note that you can find images for all the bridge components published on [Docker
|
||||||
[Docker Hub](https://hub.docker.com/u/paritytech).
|
Hub](https://hub.docker.com/u/paritytech).
|
||||||
|
|
||||||
To run a Rialto node for example, you can use the following command:
|
To run a Rialto node for example, you can use the following command:
|
||||||
|
|
||||||
@@ -247,13 +246,12 @@ docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \
|
|||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat
|
Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat server like, for
|
||||||
server like, for example, Discord. Most discussions around Polkadot and Substrate happen
|
example, Discord. Most discussions around Polkadot and Substrate happen in various Element "rooms" (channels). So,
|
||||||
in various Element "rooms" (channels). So, joining Element might be a good idea, anyway.
|
joining Element might be a good idea, anyway.
|
||||||
|
|
||||||
If you are interested in information exchange and development of Polkadot related bridges please
|
If you are interested in information exchange and development of Polkadot related bridges please feel free to join the
|
||||||
feel free to join the [Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation)
|
[Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) Element channel.
|
||||||
Element channel.
|
|
||||||
|
|
||||||
The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element
|
The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element channel is most suited
|
||||||
channel is most suited for discussions regarding Substrate itself.
|
for discussions regarding Substrate itself.
|
||||||
|
|||||||
+8
-4
@@ -4,11 +4,15 @@ Thanks for helping make the Parity ecosystem more secure. Security is one of our
|
|||||||
|
|
||||||
## Reporting a vulnerability
|
## Reporting a vulnerability
|
||||||
|
|
||||||
If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it in the public forum as it can cause more damage, rather than giving real help to the ecosystem.
|
If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it
|
||||||
|
in the public forum as it can cause more damage, rather than giving real help to the ecosystem.
|
||||||
|
|
||||||
Security vulnerabilities should be reported by the [contact form](https://security-submission.parity.io/).
|
Security vulnerabilities should be reported by the [contact form](https://security-submission.parity.io/).
|
||||||
|
|
||||||
If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information about our Bug Bounty Program.
|
If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission.
|
||||||
|
Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information
|
||||||
**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for information.
|
about our Bug Bounty Program.
|
||||||
|
|
||||||
|
**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not
|
||||||
|
mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for
|
||||||
|
information.
|
||||||
|
|||||||
+106
-103
@@ -1,83 +1,85 @@
|
|||||||
# High-Level Bridge Documentation
|
# High-Level Bridge Documentation
|
||||||
|
|
||||||
This document gives a brief, abstract description of main components that may be found in this repository.
|
This document gives a brief, abstract description of main components that may be found in this repository. If you want
|
||||||
If you want to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please
|
to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please refer to the [Polkadot <>
|
||||||
refer to the [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md).
|
Kusama Bridge](./polkadot-kusama-bridge-overview.md).
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
This repo contains all components required to build a trustless connection between standalone Substrate chains,
|
This repo contains all components required to build a trustless connection between standalone Substrate chains, that are
|
||||||
that are using GRANDPA finality, their parachains or any combination of those. On top of this connection, we
|
using GRANDPA finality, their parachains or any combination of those. On top of this connection, we offer a messaging
|
||||||
offer a messaging pallet that provides means to organize messages exchange.
|
pallet that provides means to organize messages exchange.
|
||||||
|
|
||||||
On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM messaging](./polkadot-kusama-bridge-overview.md),
|
On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM
|
||||||
[encoded calls messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on.
|
messaging](./polkadot-kusama-bridge-overview.md), [encoded calls
|
||||||
|
messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on.
|
||||||
|
|
||||||
## Terminology
|
## Terminology
|
||||||
|
|
||||||
Even though we support (and require) two-way bridging, the documentation will generally talk about
|
Even though we support (and require) two-way bridging, the documentation will generally talk about a one-sided
|
||||||
a one-sided interaction. That's to say, we will only talk about syncing finality proofs and messages
|
interaction. That's to say, we will only talk about syncing finality proofs and messages from a _source_ chain to a
|
||||||
from a _source_ chain to a _target_ chain. This is because the two-sided interaction is really just the
|
_target_ chain. This is because the two-sided interaction is really just the one-sided interaction with the source and
|
||||||
one-sided interaction with the source and target chains switched.
|
target chains switched.
|
||||||
|
|
||||||
The bridge has both on-chain (pallets) and offchain (relayers) components.
|
The bridge has both on-chain (pallets) and offchain (relayers) components.
|
||||||
|
|
||||||
## On-chain components
|
## On-chain components
|
||||||
|
|
||||||
On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require
|
On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require deployment at
|
||||||
deployment at the target chain, while messages pallet needs to be deployed at both, source
|
the target chain, while messages pallet needs to be deployed at both, source and target chains.
|
||||||
and target chains.
|
|
||||||
|
|
||||||
### Bridge GRANDPA Finality Pallet
|
### Bridge GRANDPA Finality Pallet
|
||||||
|
|
||||||
A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth"
|
A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth" about
|
||||||
about the source chain headers which have been finalized. This is useful for higher level applications.
|
the source chain headers which have been finalized. This is useful for higher level applications.
|
||||||
|
|
||||||
The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications),
|
The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), generated
|
||||||
generated by the current authorities set. The GRANDPA protocol itself requires current authorities set to
|
by the current authorities set. The GRANDPA protocol itself requires current authorities set to generate explicit
|
||||||
generate explicit justification for the header that enacts next authorities set. Such headers and their finality
|
justification for the header that enacts next authorities set. Such headers and their finality proofs are called
|
||||||
proofs are called mandatory in the pallet and relayer pays no fee for such headers submission.
|
mandatory in the pallet and relayer pays no fee for such headers submission.
|
||||||
|
|
||||||
The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers
|
The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers he wants to
|
||||||
he wants to submit (with the exception of mandatory headers).
|
submit (with the exception of mandatory headers).
|
||||||
|
|
||||||
More: [pallet level documentation and code](../modules/grandpa/).
|
More: [pallet level documentation and code](../modules/grandpa/).
|
||||||
|
|
||||||
### Bridge Parachains Finality Pallet
|
### Bridge Parachains Finality Pallet
|
||||||
|
|
||||||
Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their
|
Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their finality
|
||||||
finality proofs. Instead, they rely on their relay chain finality. The parachain header is considered final,
|
proofs. Instead, they rely on their relay chain finality. The parachain header is considered final, when it is accepted
|
||||||
when it is accepted by the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras)
|
by the [`paras`
|
||||||
at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay
|
pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras)
|
||||||
chain GRANDPA gadget.
|
at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay chain
|
||||||
|
GRANDPA gadget.
|
||||||
|
|
||||||
That said, the bridge parachains pallet accepts storage proof of one or several parachain heads, inserted to the
|
That said, the bridge parachains pallet accepts storage proof of one or several parachain heads, inserted to the
|
||||||
[`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642)
|
[`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642)
|
||||||
map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras).
|
map of the [`paras`
|
||||||
|
pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras).
|
||||||
To verify this storage proof, the pallet uses relay chain header, imported earlier by the bridge GRANDPA pallet.
|
To verify this storage proof, the pallet uses relay chain header, imported earlier by the bridge GRANDPA pallet.
|
||||||
|
|
||||||
The pallet may track multiple parachains at once and those parachains may use different primitives. So the
|
The pallet may track multiple parachains at once and those parachains may use different primitives. So the parachain
|
||||||
parachain header decoding never happens at the pallet level. For maintaining the headers order, the pallet
|
header decoding never happens at the pallet level. For maintaining the headers order, the pallet uses relay chain header
|
||||||
uses relay chain header number.
|
number.
|
||||||
|
|
||||||
More: [pallet level documentation and code](../modules/parachains/).
|
More: [pallet level documentation and code](../modules/parachains/).
|
||||||
|
|
||||||
### Bridge Messages Pallet
|
### Bridge Messages Pallet
|
||||||
|
|
||||||
The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the
|
The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the target
|
||||||
target chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the
|
chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the same order they
|
||||||
same order they are sent. The pallet supports many lanes.
|
are sent. The pallet supports many lanes.
|
||||||
|
|
||||||
The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of
|
The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of messages
|
||||||
messages that have been received. Inbound lane end stores the number of messages that have been received and
|
that have been received. Inbound lane end stores the number of messages that have been received and also a map that maps
|
||||||
also a map that maps messages to relayers that have delivered those messages to the target chain.
|
messages to relayers that have delivered those messages to the target chain.
|
||||||
|
|
||||||
The pallet has three main entrypoints:
|
The pallet has three main entrypoints:
|
||||||
- the `send_message` may be used by the other runtime pallets to send the messages;
|
- the `send_message` may be used by the other runtime pallets to send the messages;
|
||||||
- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the
|
- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the dispatch
|
||||||
dispatch code;
|
code;
|
||||||
- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding
|
- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding relayers
|
||||||
relayers that have delivered the message.
|
that have delivered the message.
|
||||||
|
|
||||||
Many things are abstracted by the pallet:
|
Many things are abstracted by the pallet:
|
||||||
- the message itself may mean anything, the pallet doesn't care about its content;
|
- the message itself may mean anything, the pallet doesn't care about its content;
|
||||||
@@ -85,97 +87,98 @@ Many things are abstracted by the pallet:
|
|||||||
- the messages proof and messages delivery proof are verified outside of the pallet;
|
- the messages proof and messages delivery proof are verified outside of the pallet;
|
||||||
- the relayers incentivization scheme is defined outside of the pallet.
|
- the relayers incentivization scheme is defined outside of the pallet.
|
||||||
|
|
||||||
Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular
|
Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular storage
|
||||||
storage proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages
|
proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages pallet, in this
|
||||||
pallet, in this case, depends on one of the finality pallets. The messages are XCM messages and we are using
|
case, depends on one of the finality pallets. The messages are XCM messages and we are using XCM executor to dispatch
|
||||||
XCM executor to dispatch them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md)
|
them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) document.
|
||||||
document.
|
|
||||||
|
|
||||||
More: [pallet level documentation and code](../modules/messages/).
|
More: [pallet level documentation and code](../modules/messages/).
|
||||||
|
|
||||||
### Bridge Relayers Pallet
|
### Bridge Relayers Pallet
|
||||||
|
|
||||||
The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When
|
The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When the rewards
|
||||||
the rewards are registered and the reward amount is configured outside of the pallet.
|
are registered and the reward amount is configured outside of the pallet.
|
||||||
|
|
||||||
More: [pallet level documentation and code](../modules/relayers/).
|
More: [pallet level documentation and code](../modules/relayers/).
|
||||||
|
|
||||||
## Offchain Components
|
## Offchain Components
|
||||||
|
|
||||||
Offchain bridge components are separate processes, called relayers. Relayers are connected both to the
|
Offchain bridge components are separate processes, called relayers. Relayers are connected both to the source chain and
|
||||||
source chain and target chain nodes. Relayers are reading state of the source chain, compare it to the
|
target chain nodes. Relayers are reading state of the source chain, compare it to the state of the target chain and, if
|
||||||
state of the target chain and, if state at target chain needs to be updated, submits target chain
|
state at target chain needs to be updated, submits target chain transaction.
|
||||||
transaction.
|
|
||||||
|
|
||||||
### GRANDPA Finality Relay
|
### GRANDPA Finality Relay
|
||||||
|
|
||||||
The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to
|
The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to the Bridge GRANDPA
|
||||||
the Bridge GRANDPA Finality Pallet, deployed at the target chain. For that, the relay subscribes to
|
Finality Pallet, deployed at the target chain. For that, the relay subscribes to the source chain GRANDPA justifications
|
||||||
the source chain GRANDPA justifications stream and submits every new justification it sees to the
|
stream and submits every new justification it sees to the target chain GRANDPA light client. In addition, relay is
|
||||||
target chain GRANDPA light client. In addition, relay is searching for mandatory headers and
|
searching for mandatory headers and submits their justifications - without that the pallet will be unable to move
|
||||||
submits their justifications - without that the pallet will be unable to move forward.
|
forward.
|
||||||
|
|
||||||
More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and code](../relays/finality/).
|
More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and
|
||||||
|
code](../relays/finality/).
|
||||||
|
|
||||||
### Parachains Finality Relay
|
### Parachains Finality Relay
|
||||||
|
|
||||||
The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the
|
The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the tracked
|
||||||
tracked parachain nodes. The relay looks at the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642)
|
parachain nodes. The relay looks at the
|
||||||
map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras)
|
[`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642)
|
||||||
in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at
|
map of the [`paras`
|
||||||
the target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits**
|
pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras)
|
||||||
until header `B` or one of its ancestors appears at the target chain. Once it is available, the storage
|
in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at the
|
||||||
proof of the map entry is generated and is submitted to the target chain.
|
target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** until header `B`
|
||||||
|
or one of its ancestors appears at the target chain. Once it is available, the storage proof of the map entry is
|
||||||
|
generated and is submitted to the target chain.
|
||||||
|
|
||||||
As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains
|
As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains finality relay
|
||||||
finality relay requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or
|
requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or any of its children's finality
|
||||||
any of its children's finality at source won't be relayed at target, and target chain
|
at source won't be relayed at target, and target chain won't be able to verify generated storage proof.
|
||||||
won't be able to verify generated storage proof.
|
|
||||||
|
|
||||||
More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/).
|
More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/).
|
||||||
|
|
||||||
### Messages Relay
|
### Messages Relay
|
||||||
|
|
||||||
Messages relay is actually two relays that are running in a single process: messages delivery relay and
|
Messages relay is actually two relays that are running in a single process: messages delivery relay and delivery
|
||||||
delivery confirmation relay. Even though they are more complex and have many caveats, the overall algorithm
|
confirmation relay. Even though they are more complex and have many caveats, the overall algorithm is the same as in
|
||||||
is the same as in other relays.
|
other relays.
|
||||||
|
|
||||||
Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new
|
Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new messages are
|
||||||
messages are queued there. Once they appear at the source block `B`, the relay start waiting for the block
|
queued there. Once they appear at the source block `B`, the relay start waiting for the block `B` or its descendant
|
||||||
`B` or its descendant appear at the target chain. Then the messages storage proof is generated and submitted
|
appear at the target chain. Then the messages storage proof is generated and submitted to the bridge messages pallet at
|
||||||
to the bridge messages pallet at the target chain. In addition, the transaction may include the storage proof
|
the target chain. In addition, the transaction may include the storage proof of the outbound lane state - that proves
|
||||||
of the outbound lane state - that proves that relayer rewards have been paid and this data (map of relay
|
that relayer rewards have been paid and this data (map of relay accounts to the delivered messages) may be pruned from
|
||||||
accounts to the delivered messages) may be pruned from the inbound lane state at the target chain.
|
the inbound lane state at the target chain.
|
||||||
|
|
||||||
Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new
|
Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new messages are
|
||||||
messages are delivered to the target chain, the corresponding _source chain account_ is inserted to the
|
delivered to the target chain, the corresponding _source chain account_ is inserted to the map in the inbound lane data.
|
||||||
map in the inbound lane data. Relay detects that, say, at the target chain block `B` and waits until that
|
Relay detects that, say, at the target chain block `B` and waits until that block or its descendant appears at the
|
||||||
block or its descendant appears at the source chain. Once that happens, the relay crafts a storage proof of
|
source chain. Once that happens, the relay crafts a storage proof of that data and sends it to the messages pallet,
|
||||||
that data and sends it to the messages pallet, deployed at the source chain.
|
deployed at the source chain.
|
||||||
|
|
||||||
As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages
|
As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages relay
|
||||||
relay submits transactions to both source and target chains, it requires both _source-to-target_ and
|
submits transactions to both source and target chains, it requires both _source-to-target_ and _target-to-source_
|
||||||
_target-to-source_ finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays,
|
finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, depending on the type of
|
||||||
depending on the type of connected chain.
|
connected chain.
|
||||||
|
|
||||||
More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and code](../relays/messages/).
|
More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and
|
||||||
|
code](../relays/messages/).
|
||||||
|
|
||||||
### Complex Relay
|
### Complex Relay
|
||||||
|
|
||||||
Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory
|
Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory GRANDPA
|
||||||
GRANDPA header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it
|
header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it sees, will have to
|
||||||
sees, will have to pay a (quite large) cost. And if no messages are sent through the bridge, that is just
|
pay a (quite large) cost. And if no messages are sent through the bridge, that is just waste of money.
|
||||||
waste of money.
|
|
||||||
|
|
||||||
We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions
|
We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions that are
|
||||||
that are required for the messages/confirmations delivery. This mode starts two message relays (in both
|
required for the messages/confirmations delivery. This mode starts two message relays (in both directions). All required
|
||||||
directions). All required finality relays are also started in a special _on-demand_ mode. In this mode they
|
finality relays are also started in a special _on-demand_ mode. In this mode they do not submit any headers without
|
||||||
do not submit any headers without special request. As always, the only exception is when GRANDPA finality
|
special request. As always, the only exception is when GRANDPA finality relay sees the mandatory header - it is
|
||||||
relay sees the mandatory header - it is submitted without such request.
|
submitted without such request.
|
||||||
|
|
||||||
The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations
|
The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations to be
|
||||||
to be delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and
|
delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and then message relay
|
||||||
then message relay may perform its job. If on-demand relay is a parachain finality relay, it also runs its
|
may perform its job. If on-demand relay is a parachain finality relay, it also runs its own on-demand GRANDPA relay,
|
||||||
own on-demand GRANDPA relay, which is used to relay required relay chain headers.
|
which is used to relay required relay chain headers.
|
||||||
|
|
||||||
More: [Complex Relay Sequence Diagram](./complex-relay.html), [code](../relays/bin-substrate/src/cli/relay_headers_and_messages/).
|
More: [Complex Relay Sequence Diagram](./complex-relay.html),
|
||||||
|
[code](../relays/bin-substrate/src/cli/relay_headers_and_messages/).
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
# Polkadot <> Kusama Bridge Overview
|
# Polkadot <> Kusama Bridge Overview
|
||||||
|
|
||||||
This document describes how we use all components, described in the [High-Level Bridge Documentation](./high-level-overview.md),
|
This document describes how we use all components, described in the [High-Level Bridge
|
||||||
to build the XCM bridge between Kusama and Polkadot. In this case, our components merely work as a XCM transport
|
Documentation](./high-level-overview.md), to build the XCM bridge between Kusama and Polkadot. In this case, our
|
||||||
(like XCMP/UMP/HRMP), between chains that are not a part of the same consensus system.
|
components merely work as a XCM transport (like XCMP/UMP/HRMP), between chains that are not a part of the same consensus
|
||||||
|
system.
|
||||||
|
|
||||||
The overall architecture may be seen in [this diagram](./polkadot-kusama-bridge.html).
|
The overall architecture may be seen in [this diagram](./polkadot-kusama-bridge.html).
|
||||||
|
|
||||||
## Bridge Hubs
|
## Bridge Hubs
|
||||||
|
|
||||||
All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains.
|
All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains. That's
|
||||||
That's why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama
|
why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama Bridge Hub under
|
||||||
Bridge Hub under Kusama consensus.
|
Kusama consensus.
|
||||||
|
|
||||||
The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to
|
The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to use
|
||||||
use our bridge hubs too and have their pallets there.
|
our bridge hubs too and have their pallets there.
|
||||||
|
|
||||||
The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub.
|
The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub. The
|
||||||
The runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs.
|
runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs.
|
||||||
|
|
||||||
## Connecting Parachains
|
## Connecting Parachains
|
||||||
|
|
||||||
You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need
|
You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need to
|
||||||
to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will
|
use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will just
|
||||||
just queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains.
|
queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains.
|
||||||
|
|
||||||
Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two
|
Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two parachains would
|
||||||
parachains would allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama
|
allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama accounts to hold wrapped DOT tokens.
|
||||||
accounts to hold wrapped DOT tokens.
|
|
||||||
|
|
||||||
For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later,
|
For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, when
|
||||||
when other parachains will join the bridge, they will be using other lanes for their messages.
|
other parachains will join the bridge, they will be using other lanes for their messages.
|
||||||
|
|
||||||
## Running Relayers
|
## Running Relayers
|
||||||
|
|
||||||
@@ -38,9 +38,9 @@ justifications to the bridge hubs at the other side. It'll also relay finalized
|
|||||||
Hub heads. This will only happen when messages will be queued at hubs. So most of time relayer will be idle.
|
Hub heads. This will only happen when messages will be queued at hubs. So most of time relayer will be idle.
|
||||||
|
|
||||||
There's no any active relayer sets, or something like that. Anyone may start its own relayer and relay queued messages.
|
There's no any active relayer sets, or something like that. Anyone may start its own relayer and relay queued messages.
|
||||||
We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost.
|
We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost. Apart
|
||||||
Apart from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have
|
from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have a mechanism
|
||||||
a mechanism for rewarding relayers.
|
for rewarding relayers.
|
||||||
|
|
||||||
### Compensating the Cost of Message Delivery Transactions
|
### Compensating the Cost of Message Delivery Transactions
|
||||||
|
|
||||||
@@ -56,51 +56,49 @@ is the relayer, which is following our rules:
|
|||||||
|
|
||||||
- we compensate the cost of message delivery transactions that have actually delivered the messages. So if your
|
- we compensate the cost of message delivery transactions that have actually delivered the messages. So if your
|
||||||
transaction has claimed to deliver messages `[42, 43, 44]`, but, because of some reasons, has actually delivered
|
transaction has claimed to deliver messages `[42, 43, 44]`, but, because of some reasons, has actually delivered
|
||||||
messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then
|
messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then the relayer
|
||||||
the relayer pays the full cost of the transaction;
|
pays the full cost of the transaction;
|
||||||
|
|
||||||
- we compensate the cost of message delivery and all required finality calls, if they are part of the same
|
- we compensate the cost of message delivery and all required finality calls, if they are part of the same
|
||||||
[`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326)
|
[`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326)
|
||||||
transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used
|
transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used to
|
||||||
to prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they
|
prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they are not
|
||||||
are not linked together, the relayer pays the full transaction cost.
|
linked together, the relayer pays the full transaction cost.
|
||||||
|
|
||||||
Please keep in mind that the fee of "zero-cost" transactions is still withdrawn from the relayer account. But the
|
Please keep in mind that the fee of "zero-cost" transactions is still withdrawn from the relayer account. But the
|
||||||
compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer
|
compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer may
|
||||||
may later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call.
|
later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call.
|
||||||
|
|
||||||
*A side note*: why we don't simply set the cost of useful transactions to zero? That's because the bridge has its cost.
|
*A side note*: why we don't simply set the cost of useful transactions to zero? That's because the bridge has its cost.
|
||||||
If we won't take any fees, it would mean that the sender is not obliged to pay for its messages. And Bridge Hub
|
If we won't take any fees, it would mean that the sender is not obliged to pay for its messages. And Bridge Hub
|
||||||
collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later,
|
collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later, in
|
||||||
in the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section.
|
the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section.
|
||||||
|
|
||||||
### Message Delivery Confirmation Rewards
|
### Message Delivery Confirmation Rewards
|
||||||
|
|
||||||
In addition to the "zero-cost" message delivery transactions, the relayer is also rewarded for:
|
In addition to the "zero-cost" message delivery transactions, the relayer is also rewarded for:
|
||||||
|
|
||||||
- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge
|
- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge Hub.;
|
||||||
Hub.;
|
|
||||||
|
|
||||||
- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms
|
- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms delivery
|
||||||
delivery of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It
|
of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It receives some fee
|
||||||
receives some fee for confirming messages, delivered by other relayers.
|
for confirming messages, delivered by other relayers.
|
||||||
|
|
||||||
Both rewards may be claimed using the `pallet_bridge_relayers::claim_rewards` call at the Source Bridge Hub.
|
Both rewards may be claimed using the `pallet_bridge_relayers::claim_rewards` call at the Source Bridge Hub.
|
||||||
|
|
||||||
### Who is Rewarding Relayers
|
### Who is Rewarding Relayers
|
||||||
|
|
||||||
Obviously, there should be someone who is paying relayer rewards. We want bridge transactions to have a cost, so we
|
Obviously, there should be someone who is paying relayer rewards. We want bridge transactions to have a cost, so we
|
||||||
can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides
|
can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides of the bridge
|
||||||
of the bridge to cover relayer rewards.
|
to cover relayer rewards.
|
||||||
|
|
||||||
Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will
|
Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will have an account
|
||||||
have an account at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama
|
at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama Bridge Hub. The sovereign accounts
|
||||||
Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the
|
are used as a source of funds when the relayer is calling the `pallet_bridge_relayers::claim_rewards`.
|
||||||
`pallet_bridge_relayers::claim_rewards`.
|
|
||||||
|
|
||||||
Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g.
|
Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. Kusama
|
||||||
Kusama Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign account
|
Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign
|
||||||
is not used to cover rewards of bridging with some other Polkadot Parachain.
|
account is not used to cover rewards of bridging with some other Polkadot Parachain.
|
||||||
|
|
||||||
### Multiple Relayers and Rewards
|
### Multiple Relayers and Rewards
|
||||||
|
|
||||||
@@ -108,25 +106,24 @@ Our goal is to incentivize running honest relayers. But we have no relayers sets
|
|||||||
message delivery transaction, hoping that the cost of this transaction will be compensated. So what if some message is
|
message delivery transaction, hoping that the cost of this transaction will be compensated. So what if some message is
|
||||||
currently queued and two relayers are submitting two identical message delivery transactions at once? Without any
|
currently queued and two relayers are submitting two identical message delivery transactions at once? Without any
|
||||||
special means, the cost of first included transaction will be compensated and the cost of the other one won't. A honest,
|
special means, the cost of first included transaction will be compensated and the cost of the other one won't. A honest,
|
||||||
but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which
|
but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which may be
|
||||||
may be used by other useful transactions.
|
used by other useful transactions.
|
||||||
|
|
||||||
To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages! {}](../bin/runtime-common/src/lib.rs)
|
To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages!
|
||||||
and [RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are
|
{}](../bin/runtime-common/src/lib.rs) and
|
||||||
preventing bridge transactions with obsolete data from including into the block. We are rejecting following
|
[RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are preventing
|
||||||
transactions:
|
bridge transactions with obsolete data from including into the block. We are rejecting following transactions:
|
||||||
|
|
||||||
- transactions, that are submitting the GRANDPA justification for the best finalized header, or one of its ancestors;
|
- transactions, that are submitting the GRANDPA justification for the best finalized header, or one of its ancestors;
|
||||||
|
|
||||||
- transactions, that are submitting the proof of the current best parachain head, or one of its ancestors;
|
- transactions, that are submitting the proof of the current best parachain head, or one of its ancestors;
|
||||||
|
|
||||||
- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered,
|
- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered, the
|
||||||
the transaction is not rejected;
|
transaction is not rejected;
|
||||||
|
|
||||||
- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new,
|
- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new, the
|
||||||
the transaction is not rejected;
|
transaction is not rejected;
|
||||||
|
|
||||||
- [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326)
|
- [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326)
|
||||||
transactions, that have both finality and message delivery calls. All restrictions from the
|
transactions, that have both finality and message delivery calls. All restrictions from the [Compensating the Cost of
|
||||||
[Compensating the Cost of Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions)
|
Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions) are applied.
|
||||||
are applied.
|
|
||||||
|
|||||||
+145
-172
@@ -1,8 +1,7 @@
|
|||||||
# Bridge Messages Pallet
|
# Bridge Messages Pallet
|
||||||
|
|
||||||
The messages pallet is used to deliver messages from source chain to target chain. Message is
|
The messages pallet is used to deliver messages from source chain to target chain. Message is (almost) opaque to the
|
||||||
(almost) opaque to the module and the final goal is to hand message to the message dispatch
|
module and the final goal is to hand message to the message dispatch mechanism.
|
||||||
mechanism.
|
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
@@ -14,229 +13,203 @@ mechanism.
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Message lane is an unidirectional channel, where messages are sent from source chain to the target
|
Message lane is an unidirectional channel, where messages are sent from source chain to the target chain. At the same
|
||||||
chain. At the same time, a single instance of messages module supports both outbound lanes and
|
time, a single instance of messages module supports both outbound lanes and inbound lanes. So the chain where the module
|
||||||
inbound lanes. So the chain where the module is deployed (this chain), may act as a source chain for
|
is deployed (this chain), may act as a source chain for outbound messages (heading to a bridged chain) and as a target
|
||||||
outbound messages (heading to a bridged chain) and as a target chain for inbound messages (coming
|
chain for inbound messages (coming from a bridged chain).
|
||||||
from a bridged chain).
|
|
||||||
|
|
||||||
Messages module supports multiple message lanes. Every message lane is identified with a 4-byte
|
Messages module supports multiple message lanes. Every message lane is identified with a 4-byte identifier. Messages
|
||||||
identifier. Messages sent through the lane are assigned unique (for this lane) increasing integer
|
sent through the lane are assigned unique (for this lane) increasing integer value that is known as nonce ("number that
|
||||||
value that is known as nonce ("number that can only be used once"). Messages that are sent over the
|
can only be used once"). Messages that are sent over the same lane are guaranteed to be delivered to the target chain in
|
||||||
same lane are guaranteed to be delivered to the target chain in the same order they're sent from
|
the same order they're sent from the source chain. In other words, message with nonce `N` will be delivered right before
|
||||||
the source chain. In other words, message with nonce `N` will be delivered right before delivering a
|
delivering a message with nonce `N+1`.
|
||||||
message with nonce `N+1`.
|
|
||||||
|
|
||||||
Single message lane may be seen as a transport channel for single application (onchain, offchain or
|
Single message lane may be seen as a transport channel for single application (onchain, offchain or mixed). At the same
|
||||||
mixed). At the same time the module itself never dictates any lane or message rules. In the end, it
|
time the module itself never dictates any lane or message rules. In the end, it is the runtime developer who defines
|
||||||
is the runtime developer who defines what message lane and message mean for this runtime.
|
what message lane and message mean for this runtime.
|
||||||
|
|
||||||
In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane
|
In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane as a channel of
|
||||||
as a channel of communication between two parachains of different relay chains. For example, lane
|
communication between two parachains of different relay chains. For example, lane `[0, 0, 0, 0]` is used for Polkadot <>
|
||||||
`[0, 0, 0, 0]` is used for Polkadot <> Kusama Asset Hub communications. Other lanes may be used to
|
Kusama Asset Hub communications. Other lanes may be used to bridge other parachains.
|
||||||
bridge other parachains.
|
|
||||||
|
|
||||||
## Message Workflow
|
## Message Workflow
|
||||||
|
|
||||||
The pallet is not intended to be used by end users and provides no public calls to send the message.
|
The pallet is not intended to be used by end users and provides no public calls to send the message. Instead, it
|
||||||
Instead, it provides runtime-internal method that allows other pallets (or other runtime code) to queue
|
provides runtime-internal method that allows other pallets (or other runtime code) to queue outbound messages.
|
||||||
outbound messages.
|
|
||||||
|
|
||||||
The message "appears" when some runtime code calls the `send_message()` method of the pallet.
|
The message "appears" when some runtime code calls the `send_message()` method of the pallet. The submitter specifies
|
||||||
The submitter specifies the lane that they're willing to use and the message itself. If some fee must
|
the lane that they're willing to use and the message itself. If some fee must be paid for sending the message, it must
|
||||||
be paid for sending the message, it must be paid outside of the pallet. If a message passes all checks
|
be paid outside of the pallet. If a message passes all checks (that include, for example, message size check, disabled
|
||||||
(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and
|
lane check, ...), the nonce is assigned and the message is stored in the module storage. The message is in an
|
||||||
the message is stored in the module storage. The message is in an "undelivered" state now.
|
"undelivered" state now.
|
||||||
|
|
||||||
We assume that there are external, offchain actors, called relayers, that are submitting module
|
We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to
|
||||||
related transactions to both target and source chains. The pallet itself has no assumptions about
|
both target and source chains. The pallet itself has no assumptions about relayers incentivization scheme, but it has
|
||||||
relayers incentivization scheme, but it has some callbacks for paying rewards. See
|
some callbacks for paying rewards. See [Integrating Messages Module into
|
||||||
[Integrating Messages Module into runtime](#Integrating-Messages-Module-into-runtime)
|
runtime](#Integrating-Messages-Module-into-runtime) for details.
|
||||||
for details.
|
|
||||||
|
|
||||||
Eventually, some relayer would notice this message in the "undelivered" state and it would decide to
|
Eventually, some relayer would notice this message in the "undelivered" state and it would decide to deliver this
|
||||||
deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery
|
message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery transaction) for the messages module
|
||||||
transaction) for the messages module instance, deployed at the target chain. Relayer provides
|
instance, deployed at the target chain. Relayer provides its account id at the source chain, the proof of message (or
|
||||||
its account id at the source chain, the proof of message (or several messages), the number of
|
several messages), the number of messages in the transaction and their cumulative dispatch weight. Once a transaction is
|
||||||
messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the
|
mined, the message is considered "delivered".
|
||||||
message is considered "delivered".
|
|
||||||
|
|
||||||
Once a message is delivered, the relayer may want to confirm delivery back to the source chain.
|
Once a message is delivered, the relayer may want to confirm delivery back to the source chain. There are two reasons
|
||||||
There are two reasons why it would want to do that. The first is that we intentionally limit number
|
why it would want to do that. The first is that we intentionally limit number of "delivered", but not yet "confirmed"
|
||||||
of "delivered", but not yet "confirmed" messages at inbound lanes
|
messages at inbound lanes (see [What about other Constants in the Messages Module Configuration
|
||||||
(see [What about other Constants in the Messages Module Configuration Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation).
|
Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). So at some point, the
|
||||||
So at some point, the target chain may stop accepting new messages until relayers confirm some of
|
target chain may stop accepting new messages until relayers confirm some of these. The second is that if the relayer
|
||||||
these. The second is that if the relayer wants to be rewarded for delivery, it must prove the fact
|
wants to be rewarded for delivery, it must prove the fact that it has actually delivered the message. And this proof may
|
||||||
that it has actually delivered the message. And this proof may only be generated after the delivery
|
only be generated after the delivery transaction is mined. So relayer crafts the `receive_messages_delivery_proof()`
|
||||||
transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka
|
transaction (aka confirmation transaction) for the messages module instance, deployed at the source chain. Once this
|
||||||
confirmation transaction) for the messages module instance, deployed at the source chain. Once
|
transaction is mined, the message is considered "confirmed".
|
||||||
this transaction is mined, the message is considered "confirmed".
|
|
||||||
|
|
||||||
The "confirmed" state is the final state of the message. But there's one last thing related to the
|
The "confirmed" state is the final state of the message. But there's one last thing related to the message - the fact
|
||||||
message - the fact that it is now "confirmed" and reward has been paid to the relayer (or at least
|
that it is now "confirmed" and reward has been paid to the relayer (or at least callback for this has been called), must
|
||||||
callback for this has been called), must be confirmed to the target chain. Otherwise, we may reach
|
be confirmed to the target chain. Otherwise, we may reach the limit of "unconfirmed" messages at the target chain and it
|
||||||
the limit of "unconfirmed" messages at the target chain and it will stop accepting new messages. So
|
will stop accepting new messages. So relayer sometimes includes a nonce of the latest "confirmed" message in the next
|
||||||
relayer sometimes includes a nonce of the latest "confirmed" message in the next
|
|
||||||
`receive_messages_proof()` transaction, proving that some messages have been confirmed.
|
`receive_messages_proof()` transaction, proving that some messages have been confirmed.
|
||||||
|
|
||||||
## Integrating Messages Module into Runtime
|
## Integrating Messages Module into Runtime
|
||||||
|
|
||||||
As it has been said above, the messages module supports both outbound and inbound message lanes.
|
As it has been said above, the messages module supports both outbound and inbound message lanes. So if we will integrate
|
||||||
So if we will integrate a module in some runtime, it may act as the source chain runtime for
|
a module in some runtime, it may act as the source chain runtime for outbound messages and as the target chain runtime
|
||||||
outbound messages and as the target chain runtime for inbound messages. In this section, we'll
|
for inbound messages. In this section, we'll sometimes refer to the chain we're currently integrating with, as "this
|
||||||
sometimes refer to the chain we're currently integrating with, as "this chain" and the other
|
chain" and the other chain as "bridged chain".
|
||||||
chain as "bridged chain".
|
|
||||||
|
|
||||||
Messages module doesn't simply accept transactions that are claiming that the bridged chain has
|
Messages module doesn't simply accept transactions that are claiming that the bridged chain has some updated data for
|
||||||
some updated data for us. Instead of this, the module assumes that the bridged chain is able to
|
us. Instead of this, the module assumes that the bridged chain is able to prove that updated data in some way. The proof
|
||||||
prove that updated data in some way. The proof is abstracted from the module and may be of any kind.
|
is abstracted from the module and may be of any kind. In our Substrate-to-Substrate bridge we're using runtime storage
|
||||||
In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other bridges may use
|
proofs. Other bridges may use transaction proofs, Substrate header digests or anything else that may be proved.
|
||||||
transaction proofs, Substrate header digests or anything else that may be proved.
|
|
||||||
|
|
||||||
**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module
|
**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module configuration. But if
|
||||||
configuration. But if you're interested in well-probed and relatively easy integration of two
|
you're interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at
|
||||||
Substrate-based chains, you may want to look at the
|
the [bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of helpers for integration,
|
||||||
[bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of
|
which may be directly used from within your runtime. Then if you'll decide to change something in this scheme, get back
|
||||||
helpers for integration, which may be directly used from within your runtime. Then if you'll decide
|
here for detailed information.
|
||||||
to change something in this scheme, get back here for detailed information.
|
|
||||||
|
|
||||||
### General Information
|
### General Information
|
||||||
|
|
||||||
The messages module supports instances. Every module instance is supposed to bridge this chain
|
The messages module supports instances. Every module instance is supposed to bridge this chain and some bridged chain.
|
||||||
and some bridged chain. To bridge with another chain, using another instance is suggested (this
|
To bridge with another chain, using another instance is suggested (this isn't forced anywhere in the code, though). Keep
|
||||||
isn't forced anywhere in the code, though). Keep in mind, that the pallet may be used to build
|
in mind, that the pallet may be used to build virtual channels between multiple chains, as we do in our [Polkadot <>
|
||||||
virtual channels between multiple chains, as we do in our [Polkadot <> Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md).
|
Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). There, the pallet actually bridges only two parachains -
|
||||||
There, the pallet actually bridges only two parachains - Kusama Bridge Hub and Polkadot
|
Kusama Bridge Hub and Polkadot Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages
|
||||||
Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages to their
|
to their Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper
|
||||||
Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper
|
|
||||||
destination parachain within the bridged chain consensus.
|
destination parachain within the bridged chain consensus.
|
||||||
|
|
||||||
Message submitters may track message progress by inspecting module events. When Message is accepted,
|
Message submitters may track message progress by inspecting module events. When Message is accepted, the
|
||||||
the `MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that
|
`MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that has been assigned to
|
||||||
has been assigned to the message. When a message is delivered to the target chain, the `MessagesDelivered`
|
the message. When a message is delivered to the target chain, the `MessagesDelivered` event is emitted from the
|
||||||
event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains
|
`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane identifier and
|
||||||
the message lane identifier and inclusive range of delivered message nonces.
|
inclusive range of delivered message nonces.
|
||||||
|
|
||||||
The pallet provides no means to get the result of message dispatch at the target chain. If that is
|
The pallet provides no means to get the result of message dispatch at the target chain. If that is required, it must be
|
||||||
required, it must be done outside of the pallet. For example, XCM messages, when dispatched, have
|
done outside of the pallet. For example, XCM messages, when dispatched, have special instructions to send some data back
|
||||||
special instructions to send some data back to the sender. Other dispatchers may use similar
|
to the sender. Other dispatchers may use similar mechanism for that.
|
||||||
mechanism for that.
|
|
||||||
### How to plug-in Messages Module to Send Messages to the Bridged Chain?
|
### How to plug-in Messages Module to Send Messages to the Bridged Chain?
|
||||||
|
|
||||||
The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with
|
The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with outbound messages. The
|
||||||
outbound messages. The `pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the
|
`pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the bridged chain as the target for our outbound
|
||||||
bridged chain as the target for our outbound messages. It must be able to check that the bridged
|
messages. It must be able to check that the bridged chain may accept our message - like that the message has size below
|
||||||
chain may accept our message - like that the message has size below maximal possible transaction
|
maximal possible transaction size of the chain and so on. And when the relayer sends us a confirmation transaction, this
|
||||||
size of the chain and so on. And when the relayer sends us a confirmation transaction, this
|
implementation must be able to parse and verify the proof of messages delivery. Normally, you would reuse the same
|
||||||
implementation must be able to parse and verify the proof of messages delivery. Normally, you would
|
(configurable) type on all chains that are sending messages to the same bridged chain.
|
||||||
reuse the same (configurable) type on all chains that are sending messages to the same bridged
|
|
||||||
chain.
|
|
||||||
|
|
||||||
The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound
|
The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The
|
||||||
messages. The simplest callback may just accept all messages. But in this case you'll need to answer
|
simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will
|
||||||
many questions first. Who will pay for the delivery and confirmation transaction? Are we sure that
|
pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the
|
||||||
someone will ever deliver this message to the bridged chain? Are we sure that we don't bloat our
|
bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is
|
||||||
runtime storage by accepting this message? What if the message is improperly encoded or has some
|
improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to
|
||||||
fields set to invalid values? Answering all those (and similar) questions would lead to correct
|
correct implementation.
|
||||||
implementation.
|
|
||||||
|
|
||||||
There's another thing to consider when implementing type for use in
|
There's another thing to consider when implementing type for use in
|
||||||
`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes
|
`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll
|
||||||
identically, or they'll have different sets of verification rules? For example, you may reserve
|
have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some
|
||||||
lane#1 for messages coming from some 'wrapped-token' pallet - then you may verify in your
|
'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet.
|
||||||
implementation that the origin is associated with this pallet. Lane#2 may be reserved for 'system'
|
Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate
|
||||||
messages and you may charge zero fee for such messages. You may have some rate limiting for messages
|
limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is
|
||||||
sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is
|
|
||||||
all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation.
|
all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation.
|
||||||
|
|
||||||
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation
|
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation transaction is
|
||||||
transaction is received, we call the `pay_reward()` method, passing the range of delivered messages.
|
received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the
|
||||||
You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its
|
[`pallet-bridge-relayers`](../relayers/) pallet and its
|
||||||
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible
|
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible implementation. It
|
||||||
implementation. It allows you to pay fixed reward for relaying the message and some of its portion
|
allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery.
|
||||||
for confirming delivery.
|
|
||||||
|
|
||||||
### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do?
|
### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do?
|
||||||
|
|
||||||
You should be looking at the `bp_messages::source_chain::ForbidOutboundMessages` structure
|
You should be looking at the `bp_messages::source_chain::ForbidOutboundMessages` structure
|
||||||
[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements
|
[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements all required traits and will
|
||||||
all required traits and will simply reject all transactions, related to outbound messages.
|
simply reject all transactions, related to outbound messages.
|
||||||
|
|
||||||
### How to plug-in Messages Module to Receive Messages from the Bridged Chain?
|
### How to plug-in Messages Module to Receive Messages from the Bridged Chain?
|
||||||
|
|
||||||
The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with
|
The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with inbound messages. The
|
||||||
inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the
|
`pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the bridged chain as the source of our inbound
|
||||||
bridged chain as the source of our inbound messages. When relayer sends us a delivery transaction,
|
messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof
|
||||||
this implementation must be able to parse and verify the proof of messages wrapped in this
|
of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are
|
||||||
transaction. Normally, you would reuse the same (configurable) type on all chains that are sending
|
sending messages to the same bridged chain.
|
||||||
messages to the same bridged chain.
|
|
||||||
|
|
||||||
The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered
|
The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered messages. Apart from
|
||||||
messages. Apart from actually dispatching the message, the implementation must return the correct
|
actually dispatching the message, the implementation must return the correct dispatch weight of the message before
|
||||||
dispatch weight of the message before dispatch is called.
|
dispatch is called.
|
||||||
|
|
||||||
### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do?
|
### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do?
|
||||||
|
|
||||||
You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from
|
You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from the
|
||||||
the [`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It
|
[`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It implements all required traits
|
||||||
implements all required traits and will simply reject all transactions, related to inbound messages.
|
and will simply reject all transactions, related to inbound messages.
|
||||||
|
|
||||||
### What about other Constants in the Messages Module Configuration Trait?
|
### What about other Constants in the Messages Module Configuration Trait?
|
||||||
|
|
||||||
Two settings that are used to check messages in the `send_message()` function. The
|
Two settings that are used to check messages in the `send_message()` function. The
|
||||||
`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that
|
`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that may be used to send
|
||||||
may be used to send messages. All messages sent using other lanes are rejected. All messages that have
|
messages. All messages sent using other lanes are rejected. All messages that have size above
|
||||||
size above `pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected.
|
`pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected.
|
||||||
|
|
||||||
To be able to reward the relayer for delivering messages, we store a map of message nonces range =>
|
To be able to reward the relayer for delivering messages, we store a map of message nonces range => identifier of the
|
||||||
identifier of the relayer that has delivered this range at the target chain runtime storage. If a
|
relayer that has delivered this range at the target chain runtime storage. If a relayer delivers multiple consequent
|
||||||
relayer delivers multiple consequent ranges, they're merged into single entry. So there may be more
|
ranges, they're merged into single entry. So there may be more than one entry for the same relayer. Eventually, this
|
||||||
than one entry for the same relayer. Eventually, this whole map must be delivered back to the source
|
whole map must be delivered back to the source chain to confirm delivery and pay rewards. So to make sure we are able to
|
||||||
chain to confirm delivery and pay rewards. So to make sure we are able to craft this confirmation
|
craft this confirmation transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure
|
||||||
transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure that
|
that the weight of processing this map is below a certain limit. Both size and processing weight mostly depend on the
|
||||||
the weight of processing this map is below a certain limit. Both size and processing weight mostly
|
number of entries. The number of entries is limited with the
|
||||||
depend on the number of entries. The number of entries is limited with the
|
`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight also depends on
|
||||||
`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight
|
the total number of messages that are being confirmed, because every confirmed message needs to be read. So there's
|
||||||
also depends on the total number of messages that are being confirmed, because every confirmed
|
another `pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that.
|
||||||
message needs to be read. So there's another
|
|
||||||
`pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that.
|
|
||||||
|
|
||||||
When choosing values for these parameters, you must also keep in mind that if proof in your scheme
|
When choosing values for these parameters, you must also keep in mind that if proof in your scheme is based on finality
|
||||||
is based on finality of headers (and it is the most obvious option for Substrate-based chains with
|
of headers (and it is the most obvious option for Substrate-based chains with finality notion), then choosing too small
|
||||||
finality notion), then choosing too small values for these parameters may cause significant delays
|
values for these parameters may cause significant delays in message delivery. That's because there are too many actors
|
||||||
in message delivery. That's because there are too many actors involved in this scheme: 1) authorities
|
involved in this scheme: 1) authorities that are finalizing headers of the target chain need to finalize header with
|
||||||
that are finalizing headers of the target chain need to finalize header with non-empty map; 2) the
|
non-empty map; 2) the headers relayer then needs to submit this header and its finality proof to the source chain; 3)
|
||||||
headers relayer then needs to submit this header and its finality proof to the source chain; 3) the
|
the messages relayer must then send confirmation transaction (storage proof of this map) to the source chain; 4) when
|
||||||
messages relayer must then send confirmation transaction (storage proof of this map) to the source
|
the confirmation transaction will be mined at some header, source chain authorities must finalize this header; 5) the
|
||||||
chain; 4) when the confirmation transaction will be mined at some header, source chain authorities
|
headers relay then needs to submit this header and its finality proof to the target chain; 6) only now the messages
|
||||||
must finalize this header; 5) the headers relay then needs to submit this header and its finality
|
relayer may submit new messages from the source to target chain and prune the entry from the map.
|
||||||
proof to the target chain; 6) only now the messages relayer may submit new messages from the source
|
|
||||||
to target chain and prune the entry from the map.
|
|
||||||
|
|
||||||
Delivery transaction requires the relayer to provide both number of entries and total number of
|
Delivery transaction requires the relayer to provide both number of entries and total number of messages in the map.
|
||||||
messages in the map. This means that the module never charges an extra cost for delivering a map -
|
This means that the module never charges an extra cost for delivering a map - the relayer would need to pay exactly for
|
||||||
the relayer would need to pay exactly for the number of entries+messages it has delivered. So the
|
the number of entries+messages it has delivered. So the best guess for values of these parameters would be the pair that
|
||||||
best guess for values of these parameters would be the pair that would occupy `N` percent of the
|
would occupy `N` percent of the maximal transaction size and weight of the source chain. The `N` should be large enough
|
||||||
maximal transaction size and weight of the source chain. The `N` should be large enough to process
|
to process large maps, at the same time keeping reserve for future source chain upgrades.
|
||||||
large maps, at the same time keeping reserve for future source chain upgrades.
|
|
||||||
|
|
||||||
## Non-Essential Functionality
|
## Non-Essential Functionality
|
||||||
|
|
||||||
There may be a special account in every runtime where the messages module is deployed. This
|
There may be a special account in every runtime where the messages module is deployed. This account, named 'module
|
||||||
account, named 'module owner', is like a module-level sudo account - he's able to halt and
|
owner', is like a module-level sudo account - he's able to halt and resume all module operations without requiring
|
||||||
resume all module operations without requiring runtime upgrade. Calls that are related to this
|
runtime upgrade. Calls that are related to this account are:
|
||||||
account are:
|
|
||||||
- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account;
|
- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account;
|
||||||
- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all
|
- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all module operations. After
|
||||||
module operations. After this call, all message-related transactions will be rejected until
|
this call, all message-related transactions will be rejected until further `resume_operations` call'. This call may be
|
||||||
further `resume_operations` call'. This call may be used when something extraordinary happens with
|
used when something extraordinary happens with the bridge;
|
||||||
the bridge;
|
- `fn resume_operations()`: module owner may call this function to resume bridge operations. The module will resume its
|
||||||
- `fn resume_operations()`: module owner may call this function to resume bridge operations. The
|
regular operations after this call.
|
||||||
module will resume its regular operations after this call.
|
|
||||||
|
|
||||||
If pallet owner is not defined, the governance may be used to make those calls.
|
If pallet owner is not defined, the governance may be used to make those calls.
|
||||||
|
|
||||||
## Messages Relay
|
## Messages Relay
|
||||||
|
|
||||||
We have an offchain actor, who is watching for new messages and submits them to the bridged chain.
|
We have an offchain actor, who is watching for new messages and submits them to the bridged chain. It is the messages
|
||||||
It is the messages relay - you may look at the [crate level documentation and the code](../../relays/messages/).
|
relay - you may look at the [crate level documentation and the code](../../relays/messages/).
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ validators. Validators validate the block and register the new parachain head in
|
|||||||
[`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645)
|
[`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645)
|
||||||
of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet,
|
of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet,
|
||||||
deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet,
|
deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet,
|
||||||
even though the names are similar.
|
even though the names are similar.
|
||||||
|
|
||||||
And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that
|
And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that
|
||||||
`Heads` map. It does that using relay chain header, that has been previously imported by the
|
`Heads` map. It does that using relay chain header, that has been previously imported by the
|
||||||
|
|||||||
Reference in New Issue
Block a user