Update project level docs (#1734)

* updated project level document

* updated high level overview document

* GRANDPA finality relay sequence diagram

* Parachains Finality Relay Sequence Diagram

* Messages Relay Sequence Diagram

* Complex Relayer Sequence Diagram

* small fix

* Polkadot <> Kusama bridge flowchart

* remove obsolete files

* started polkadot-kusama-bridge-overview.md

* continue polkadot-kusama-bridge-overview.md

* couple more sections in polkadot-kusama-bridge-overview.md

* continue polkadot-kusama-bridge-overview.md

* renew deployments readme

* fixed review suggestions

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* removed obsolete section

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* typo

* Update docs/polkadot-kusama-bridge-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/high-level-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/polkadot-kusama-bridge-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/polkadot-kusama-bridge-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/polkadot-kusama-bridge-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

* Update docs/polkadot-kusama-bridge-overview.md

Co-authored-by: Adrian Catangiu <adrian@parity.io>

Co-authored-by: Adrian Catangiu <adrian@parity.io>
This commit is contained in:
Svyatoslav Nikolsky
2023-01-09 08:44:47 +03:00
committed by Bastian Köcher
parent 64f03aaa0b
commit 7821e66bcd
8 changed files with 633 additions and 147 deletions
+37 -31
View File
@@ -10,11 +10,6 @@ Substrate chains.
🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧
**IMPORTANT**: this documentation is outdated and it is mostly related to the previous version of our
bridge. Right there's an ongoing work to make our bridge work with XCM messages. Old bridge is still
available at [encoded-calls-messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging)
tag.
## Contents
- [Installation](#installation)
@@ -97,7 +92,7 @@ description of the bridge interaction.
## Project Layout
Here's an overview of how the project is laid out. The main bits are the `node`, 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 `modules` which are used to build the blockchain's logic (a.k.a the runtime) and
the `relays` which are used to pass messages between chains.
@@ -106,16 +101,16 @@ the `relays` which are used to pass messages between chains.
│ └── ...
├── deployments // Useful tools for deploying test networks
│ └── ...
├── diagrams // Pretty pictures of the project architecture
│ └── ...
├── modules // Substrate Runtime Modules (a.k.a Pallets)
│ ├── beefy // On-Chain BEEFY Light Client (in progress)
│ ├── grandpa // On-Chain GRANDPA Light Client
│ ├── messages // Cross Chain Message Passing
│ ├── dispatch // Target Chain Message Execution
│ ├── parachains // On-Chain Parachains Light Client
│ ├── relayers // Relayer rewards registry
│ └── ...
├── primitives // Code shared between modules, runtimes, and relays
│ └── ...
├── relays // Application for sending headers and messages between chains
├── relays // Application for sending finality proofs and messages between chains
│ └── ...
└── scripts // Useful development and maintenance scripts
```
@@ -127,8 +122,11 @@ on each side of the bridge (source and target chain).
There are 2 ways to run the bridge, described below:
- building & running from source
- running a Docker Compose setup (recommended).
- building & running from source: with this option, you'll be able to run the bridge between two standalone
chains that 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,
complex relays and more.
### Using the Source
@@ -204,7 +202,33 @@ You will also see the message lane relayers listening for new messages.
To send a message see the ["How to send a message" section](#how-to-send-a-message).
### Full Network Docker Compose Setup
### 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
`Trap(43)` message.
```bash
# In `parity-bridges-common` folder
./scripts/send-message-from-millau-rialto.sh
```
After sending a message you will see the following logs showing a message was successfully sent:
```
INFO bridge Sending message to Rialto. Size: 5.
TRACE bridge Sent transaction to Millau node: 0x5e68...
```
And at the Rialto node logs you'll something like this:
```
... runtime::bridge-dispatch: Going to execute message ([0, 0, 0, 0], 1) (...), Trap(43)])
... runtime::bridge-dispatch: Incoming message ([0, 0, 0, 0], 1) dispatched with result: Incomplete(2000000000, Trap(43))
```
It means that the message has been delivered and successfully dispatched.
## Full Network Docker Compose Setup
For a more sophisticated deployment which includes bidirectional header sync, message passing,
monitoring dashboards, etc. see the [Deployments README](./deployments/README.md).
@@ -220,24 +244,6 @@ docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \
--rpc-cors=all --unsafe-rpc-external --unsafe-ws-external
```
### How to send a message
In this section we'll show you how to quickly send a bridge message, if you want to
interact with and test the bridge see more details in [send message](./docs/send-message.md)
```bash
# In `parity-bridges-common` folder
./scripts/send-message-from-millau-rialto.sh remark
```
After sending a message you will see the following logs showing a message was successfully sent:
```
INFO bridge Sending message to Rialto. Size: 286. Dispatch weight: 1038000. Fee: 275,002,568
INFO bridge Signed Millau Call: 0x7904...
TRACE bridge Sent transaction to Millau node: 0x5e68...
```
## Community
Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat
+85
View File
@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Complex Relay</title>
</head>
<body>
<h1>Complex Relay</h1>
<p>
Both Source Chain and Target Chains have Bridge Messages pallets deployed. They also have required
finality pallets deployed - we don't care about finality type here - they can be either Bridge GRANDPA,
or Bridge Parachains finality pallets, or any combination of those.<br/>
</p>
<p>
There are 4-6 relayer subprocesses inside the Complex Relayer. They include two message relayers,
serving the lane in both directions and 2-4 Complex Relayers (depending on the finality type of Source
and Target Chains).<br/>
</p>
<p>
The following diagram shows the way the complex relayer serves the lane in single direction. Everything
below may be applied to the opposite direction if you'll swap the Source and Target Chains.
</p>
<div class="mermaid">
sequenceDiagram
participant Source Chain
participant Complex Relayer
participant Target Chain
Note right of Source Chain: Finalized: 480, Target Finalized: 50, Sent Messages: 42, Confirmed Messages: 42
Note left of Target Chain: Finalized: 60, Source Finalized: 420, Received Messages: 42
Source Chain ->> Source Chain: someone Sends Message 43
Source Chain ->> Source Chain: Import and Finalize Block 481
Source Chain ->> Complex Relayer: notes new outbound message 43 at Source Chain Block 481
Note right of Complex Relayer: can't deliver message 43, Source Chain Block 481 is not relayed
Complex Relayer ->> Complex Relayer: asks on-demand Finality Relayer to relay Source Chain Block 481
Source Chain ->> Complex Relayer: Read Finality Proof of Block 481
Complex Relayer ->> Target Chain: Submit Finality Proof of Block 481
Target Chain ->> Target Chain: Import and Finalize Block 61
Note left of Target Chain: Finalized: 61, Source Finalized: 481, Received Messages: 42
Source Chain ->> Complex Relayer: Read Proof of Message 43 at Block 481
Complex Relayer ->> Target Chain: Submit Proof of Message 43 at Block 481
Target Chain ->> Target Chain: Import and Finalize Block 62
Note left of Target Chain: Finalized: 62, Source Finalized: 481, Received Messages: { rewarded: 42, messages-relayer-account: [43] }
Target Chain ->> Complex Relayer: notes new unrewarded relayer at Target Chain Block 62
Note right of Complex Relayer: can't relay delivery confirmations because Target Chain Block 62 is not relayed
Complex Relayer ->> Complex Relayer: asks on-demand Finality Relayer to relay Target Chain Block 62
Target Chain ->> Complex Relayer: Read Finality Proof of Block 62
Complex Relayer ->> Source Chain: Submit Finality Proof of Block 62
Source Chain ->> Source Chain: Import and Finalize Block 482
Note right of Source Chain: Finalized: 482, Target Finalized: 62, Confirmed Messages: 42
Target Chain ->> Complex Relayer: Read Proof of Message 43 Delivery at Block 62
Complex Relayer ->> Source Chain: Submit Proof of Message 43 Delivery at Block 612
Source Chain ->> Source Chain: rewards messages-relayer-account for delivering message [43]
Source Chain ->> Source Chain: prune delivered message 43 from runtime storage
Note right of Source Chain: Finalized: 482, Target Finalized: 61, Confirmed Messages: 43
Source Chain ->> Source Chain: someone Sends Message 44
Source Chain ->> Source Chain: Import and Finalize Block 483
Source Chain ->> Complex Relayer: notes new outbound message 44 at Source Chain Block 483 and new confirmed message 43
Note right of Complex Relayer: can't deliver message 44, Source Chain Block 483 is not relayed
Complex Relayer ->> Complex Relayer: asks on-demand Finality Relayer to relay Source Chain Block 483
Source Chain ->> Complex Relayer: Read Finality Proof of Block 483
Complex Relayer ->> Target Chain: Submit Finality Proof of Block 483
Target Chain ->> Target Chain: Import and Finalize Block 63
Note left of Target Chain: Finalized: 63, Source Finalized: 483, Received Messages: { rewarded: 42, messages-relayer-account: [43] }
Source Chain ->> Complex Relayer: Read Proof of Message 44 and Proof of Message 43 reward at Block 483
Complex Relayer ->> Target Chain: Submit Proof of Message 44 and Proof of Message 43 reward at Block 483
Target Chain ->> Target Chain: Import and Finalize Block 64
Note left of Target Chain: Finalized: 64, Source Finalized: 483, Received Messages: { rewarded: 43, messages-relayer-account: [44] }-->
</div>
<script src="https://cdn.jsdelivr.net/npm/mermaid@8.8.4/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad: true})</script>
</body>
</html>
+47
View File
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>GRANDPA Finality Relay</title>
</head>
<body>
<h1>GRANDPA Finality Relay</h1>
<p>
Source Chain is running GRANDPA Finality Gadget. Bridge GRANDPA finality pallet is deployed at
Target Chain runtime. Relayer is configured to relay Source Chain finality to Target Chain.
</p>
<div class="mermaid">
sequenceDiagram
participant Source Chain
participant Relayer
participant Target Chain
Note left of Source Chain: Best: 500, Finalized: 480, Authorities Set Index: 42
Note right of Target Chain: Uninitialized
Source Chain ->> Relayer: Read Initialization Data
Relayer ->> Target Chain: Initialize Bridge GRANDPA Finality Pallet
Note right of Target Chain: Finalized: 480, Authorities Set Index: 42
Source Chain ->> Source Chain: Import Block 501
Source Chain ->> Source Chain: Import Block 502
Source Chain ->> Source Chain: Finalize Block 495
Source Chain ->> Relayer: Read Finality Proof of Block 495
Relayer ->> Target Chain: Finality Proof of Block 495
Note right of Target Chain: Finalized: 495, Authorities Set Index: 42
Source Chain ->> Source Chain: Import Block 503 that changes Authorities Set to 43
Source Chain ->> Source Chain: Finalize Block 500
Note left of Relayer: Relayer Misses Finality Notification for Block 500
Source Chain ->> Source Chain: Import Block 504
Source Chain ->> Source Chain: Finalize Mandatory Block 503
Source Chain ->> Source Chain: Finalize Block 504
Source Chain ->> Relayer: Read Finality Proof of Mandatory Block 503
Relayer ->> Target Chain: Finality Proof of Block 503
Note right of Target Chain: Finalized: 503, Authorities Set Index: 43
</div>
<script src="https://cdn.jsdelivr.net/npm/mermaid@8.8.4/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad: true})</script>
</body>
</html>
+132 -116
View File
@@ -1,165 +1,181 @@
# High-Level Bridge Documentation
This document gives a brief, abstract description of main components that may be found in this repository.
If you want to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please
refer to the [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md).
## Purpose
Trustless connecting between two Substrate-based chains using GRANDPA finality.
This repo contains all components required to build a trustless connection between standalone Substrate chains,
that are using GRANDPA finality, their parachains or any combination of those. On top of this connection, we
offer a messaging pallet that provides means to organize messages exchange.
## Overview
On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM messaging](./polkadot-kusama-bridge-overview.md),
[encoded calls messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on.
Even though we support two-way bridging, the documentation will generally talk about a one-sided
interaction. That's to say, we will only talk about syncing headers and messages from a _source_
chain to a _target_ chain. This is because the two-sided interaction is really just the one-sided
interaction with the source and target chains switched.
## Terminology
To understand the full interaction with the bridge, take a look at the
[testing scenarios](./testing-scenarios.md) document. It describes potential use cases and describes
how each of the layers outlined below is involved.
Even though we support (and require) two-way bridging, the documentation will generally talk about
a one-sided interaction. That's to say, we will only talk about syncing finality proofs and messages
from a _source_ chain to a _target_ chain. This is because the two-sided interaction is really just the
one-sided interaction with the source and target chains switched.
The bridge is built from various components. Here is a quick overview of the important ones.
The bridge has both on-chain (pallets) and offchain (relayers) components.
### Header Sync
## On-chain components
A light client of the source chain built into the target chain's runtime. It is a single FRAME
pallet. It provides a "source of truth" about the source chain headers which have been finalized.
This is useful for higher level applications.
On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require
deployment at the target chain, while messages pallet needs to be deployed at both, source
and target chains.
### Headers Relayer
### Bridge GRANDPA Finality Pallet
A standalone application connected to both chains. It submits every source chain header it sees to
the target chain through RPC.
A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth"
about the source chain headers which have been finalized. This is useful for higher level applications.
### Message Delivery
The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications),
generated by the current authorities set. The GRANDPA protocol itself requires current authorities set to
generate explicit justificaion for the header that enacts next authorities set. Such headers and their finality
proofs are called mandatory in the pallet and relayer pays no fee for such headers submission.
A FRAME pallet built on top of the header sync pallet. It allows users to submit messages to the
source chain, which are to be delivered to the target chain. The delivery protocol doesn't care
about the payload more than it has to. Handles replay protection and message ordering.
The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers
he wants to submit (with the exception of mandatory headers).
### Message Dispatch
More: [code](../modules/grandpa/).
A FRAME pallet responsible for interpreting the payload of delivered messages.
### Bridge Parachains Finality Pallet
### Message Relayer
Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their
finality proofs. Instead, they rely on their relay chain finality. The parachain header is considered final,
when it is accepted by the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras)
at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay
chain GRANDPA gadget.
A standalone application handling delivery of the messages from source chain to the target chain.
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)
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.
## Processes
The pallet may track multiple parachains at once and those parachains may use different primitives. So the
parachain header decoding never happens at the pallet level. For maintaining the headers order, the pallet
uses relay chain header number.
High level sequence charts of the process can be found in [a separate document](./high-level.html).
More: [code](../modules/parachains/).
### Substrate (GRANDPA) Header Sync
### Bridge Messages Pallet
The header sync pallet (`pallet-bridge-grandpa`) is an on-chain light client for chains which use
GRANDPA finality. It is part of the target chain's runtime, and accepts finality proofs from the source
chain. Verify GRANDPA finality proofs (a.k.a justifications) and track GRANDPA finality set changes.
The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the
target chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the
same order they are sent. The pallet supports many lanes.
The pallet does not care about what block production mechanism is used for the source chain
(e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. In fact the pallet does not
necessarily store all produced headers, we only import headers with valid GRANDPA justifications.
The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of
messages that have been received. Inbound lane end stores the number of messages that have been received and
also a map that maps messages to relayers that have delivered those messages to the target chain.
Referer to the [pallet documentation](../modules/grandpa/src/lib.rs) for more details.
The pallet has three main entrypoints:
- 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
dispatch code;
- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding
relayers that have delivered the message.
#### Header Relayer strategy
Many things are abstracted by the pallet:
- the message itself may mean anything, the pallet doesn't care about its content;
- the message dispatch happens during delivery, but it is decoupled from the pallet code;
- the messages proof and messages delivery proof are verified outside of the pallet;
- the relayers incentivization scheme is defined outside of the pallet.
There is currently no reward strategy for the relayers at all. They also are not required to be
staked or registered on-chain, unlike in other bridge designs. We consider the header sync to be
an essential part of the bridge and the incentivization should be happening on the higher layers.
Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular
storage proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages
pallet, in this case, depends on one of the finality pallets. The messages are XCM messages and we are using
XCM executor to dispatch them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md)
document.
At the moment, signed transactions are the only way to submit headers to the header sync pallet.
However, in the future we would like to use unsigned transactions for headers delivery. This will
allow transaction de-duplication to be done at the transaction pool level and also remove the cost
for message relayers to run header relayers.
More: [code](../modules/messages/).
### Message Passing
### Bridge Relayers Pallet
Once header sync is maintained, the target side of the bridge can receive and verify proofs about
events happening on the source chain, or its internal state. On top of this, we built a message
passing protocol which consists of two parts described in following sections: message delivery and
message dispatch.
The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When
the rewards are registered and the reward amount is configured outside of the pallet.
#### Message Lanes Delivery
More: [code](../modules/relayers/).
The [Message delivery pallet](../modules/messages/src/lib.rs) is responsible for queueing up
messages and delivering them in order on the target chain. It also dispatches messages, but we will
cover that in the next section.
## Offchain Components
The pallet supports multiple lanes (channels) where messages can be added. Every lane can be
considered completely independent from others, which allows them to make progress in parallel.
Different lanes can be configured to validated messages differently (e.g higher rewards, specific
types of payload, etc.) and may be associated with a particular "user application" built on top of
the bridge. Note that messages in the same lane MUST be delivered _in the same order_ they were
queued up.
Offchain bridge components are separate processes, called relayers. Relayers are connected both to the
source chain and target chain nodes. Relayers are reading state of the source chain, compare it to the
state of the target chain and, if state at target chain needs to be updated, submits target chain
transaction.
The message delivery protocol does not care about the payload it transports and can be coupled
with an arbitrary message dispatch mechanism that will interpret and execute the payload if delivery
conditions are met. Each delivery on the target chain is confirmed back to the source chain by the
relayer. This is so that she can collect the reward for delivering these messages.
### GRANDPA Finality Relay
Users of the pallet add their messages to an "outbound lane" on the source chain. When a block is
finalized message relayers are responsible for reading the current queue of messages and submitting
some (or all) of them to the "inbound lane" of the target chain. Each message has a `nonce`
associated with it, which serves as the ordering of messages. The inbound lane stores the last
delivered nonce to prevent replaying messages. To successfully deliver the message to the inbound lane
on target chain the relayer has to present present a storage proof which shows that the message was
part of the outbound lane on the source chain.
The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to
the Bridge GRANDPA Finality Pallet, deployed at the target chain. For that, the relay subscribes to
the source chain GRANDPA justifications stream and submits every new justification it sees to the
target chain GRANDPA light client. In addition, relay is searching for mandatory headers and
submits their justifications - without that the pallet will be unable to move forward.
During delivery of messages they are immediately dispatched on the target chain and the relayer is
required to declare the correct `weight` to cater for all messages dispatch and pay all required
fees of the target chain. To make sure the relayer is incentivised to do so, on the source chain:
- the user provides a declared dispatch weight of the payload
- the pallet calculates the expected fee on the target chain based on the declared weight
- the pallet converts the target fee into source tokens (based on a price oracle) and reserves
enough tokens to cover for the delivery, dispatch, confirmation and additional relayers reward.
More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [code](../relays/finality/).
If the declared weight turns out to be too low on the target chain the message is delivered but
it immediately fails to dispatch. The fee and reward is collected by the relayer upon confirmation
of delivery.
### Parachains Finality Relay
Due to the fact that message lanes require delivery confirmation transactions, they also strictly
require bi-directional header sync (i.e. you can't use message delivery with one-way header sync).
The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the
tracked parachain nodes. The relay looks at the [`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)
in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at
the taget 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.
#### Dispatching Messages
As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains
finality relay requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or
any of its children's finality at source won't be relayed at target, and target chain
won't be able to verify generated storage proof.
The [Message dispatch pallet](../modules/dispatch/src/lib.rs) is used to perform the actions
specified by messages which have come over the bridge. For Substrate-based chains this means
interpreting the source chain's message as a `Call` on the target chain.
More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/).
An example `Call` of the target chain would look something like this:
### Messages Relay
```rust
target_runtime::Call::Balances(target_runtime::pallet_balances::Call::transfer(recipient, amount))
```
Messages relay is actually two relays that are running in a single process: messages delivery relay and
delivery confirmation relay. Even though they are more complex and have many caveats, the overall algorithm
is the same as in other relays.
When sending a `Call` it must first be SCALE encoded and then sent to the source chain. The `Call`
is then delivered by the message lane delivery mechanism from the source chain to the target chain.
When a message is received the inbound message lane on the target chain will try and decode the
message payload into a `Call` enum. If it's successful it will be dispatched after we check that the
weight of the call does not exceed the weight declared by the sender. The relayer pays fees for
executing the transaction on the target chain, but her costs should be covered by the sender on the
source chain.
Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new
messages are queued there. Once they appear at the source block `B`, the relay start waiting for the block
`B` or its descendant appear at the target chain. Then the messages storage proof is generated and submitted
to the bridge messages pallet at the target chain. In addition, the transaction may include the storage proof
of the outbound lane state - that proves that relayer rewards have been paid and this data (map of relay
accounts to the delivered messages) may be pruned from the inbound lane state at the target chain.
When dispatching messages there are three Origins which can be used by the target chain:
1. Root Origin
2. Source Origin
3. Target Origin
Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new
messages are delivered to the target chain, the corresponding _source chain account_ is inserted to the
map in the inbound lane data. Relay detects that, say, at the target chain block `B` and waits until that
block or its descendant appears at the source chain. Once that happens, the relay crafts a storage proof of
that data and sends it to the messages pallet, deployed at the source chain.
Senders of a message can indicate which one of the three origins they would like to dispatch their
message with. However, there are restrictions on who/what is allowed to dispatch messages with a
particular origin.
As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages
relay submits transactions to both source and target chains, it requires both _source-to-target_ and
_target-to-source_ finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays,
depending on the type of connected chain.
The Root origin represents the source chain's Root account on the target chain. This origin can can
only be dispatched on the target chain if the "send message" request was made by the Root origin of
the source chain - otherwise the message will fail to be dispatched.
More: [Messages Relay Sequence Diagram](./messages-relay.html), [code](../relays/messages/).
The Source origin represents an account without a private key on the target chain. This account will
be generated/derived using the account ID of the sender on the source chain. We don't necessarily
require the source account id to be associated with a private key on the source chain either. This
is useful for representing things such as source chain proxies or pallets.
### Complex Relay
The Target origin represents an account with a private key on the target chain. The sender on the
source chain needs to prove ownership of this account by using their target chain private key to
sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and
verified by the target chain before dispatch.
Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory
GRANDPA header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it
sees, will have to pay a (quite large) cost. And if no messages are sent through the bridge, that is just
waste of money.
See [`CallOrigin` documentation](../primitives/message-dispatch/src/lib.rs) for more details.
We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions
that are required for the messages/confirmations delivery. This mode starts two message relays (in both
directions). All required finality relays are also started in a special _on-demand_ mode. In this mode they
do not submit any headers without special request. As always, the only exception is when GRANDPA finality
relay sees the mandatory header - it is submitted without such request.
#### Message Relayers Strategy
The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations
to be delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and
then message relay may perform its job. If on-demand relay is a parachain finality relay, it also runs its
own on-demand GRANDPA relay, 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/).
+78
View File
@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Messages Relay</title>
</head>
<body>
<h1>Messages Relay</h1>
<p>
Both Source Chain and Target Chains have Bridge Messages pallets deployed. They also have required
finality pallets deployed - we don't care about finality type here - they can be either Bridge GRANDPA,
or Bridge Parachains finality pallets, or any combination of those.
</p>
<p>
Finality Relayer represents two actual relayers - one relays Source Chain Finality to Target Chain.
And another one relays Target Chain Finality to Source Chain.
</p>
<div class="mermaid">
sequenceDiagram
participant Source Chain
participant Finality Relayer
participant Messages Relayer
participant Target Chain
Note right of Source Chain: Finalized: 480, Target Finalized: 50, Sent Messages: 42, Confirmed Messages: 42
Note left of Target Chain: Finalized: 60, Source Finalized: 420, Received Messages: 42
Source Chain ->> Source Chain: someone Sends Message 43
Source Chain ->> Source Chain: Import and Finalize Block 481
Source Chain ->> Messages Relayer: notes new outbound message 43 at Source Chain Block 481
Note right of Messages Relayer: can't deliver message 43, Source Chain Block 481 is not relayed
Source Chain ->> Finality Relayer: Read Finality Proof of Block 481
Finality Relayer ->> Target Chain: Submit Finality Proof of Block 481
Target Chain ->> Target Chain: Import and Finalize Block 61
Note left of Target Chain: Finalized: 61, Source Finalized: 481, Received Messages: 42
Source Chain ->> Messages Relayer: Read Proof of Message 43 at Block 481
Messages Relayer ->> Target Chain: Submit Proof of Message 43 at Block 481
Target Chain ->> Target Chain: Import and Finalize Block 62
Note left of Target Chain: Finalized: 62, Source Finalized: 481, Received Messages: { rewarded: 42, messages-relayer-account: [43] }
Target Chain ->> Messages Relayer: notes new unrewarded relayer at Target Chain Block 62
Note right of Messages Relayer: can't relay delivery confirmations because Target Chain Block 62 is not relayed
Target Chain ->> Finality Relayer: Read Finality Proof of Block 62
Finality Relayer ->> Source Chain: Submit Finality Proof of Block 62
Source Chain ->> Source Chain: Import and Finalize Block 482
Note right of Source Chain: Finalized: 482, Target Finalized: 62, Confirmed Messages: 42
Target Chain ->> Messages Relayer: Read Proof of Message 43 Delivery at Block 62
Messages Relayer ->> Source Chain: Submit Proof of Message 43 Delivery at Block 612
Source Chain ->> Source Chain: rewards messages-relayer-account for delivering message [43]
Source Chain ->> Source Chain: prune delivered message 43 from runtime storage
Note right of Source Chain: Finalized: 482, Target Finalized: 61, Confirmed Messages: 43
Source Chain ->> Source Chain: someone Sends Message 44
Source Chain ->> Source Chain: Import and Finalize Block 483
Source Chain ->> Messages Relayer: notes new outbound message 44 at Source Chain Block 483 and new confirmed message 43
Note right of Messages Relayer: can't deliver message 44, Source Chain Block 483 is not relayed
Source Chain ->> Finality Relayer: Read Finality Proof of Block 483
Finality Relayer ->> Target Chain: Submit Finality Proof of Block 483
Target Chain ->> Target Chain: Import and Finalize Block 63
Note left of Target Chain: Finalized: 63, Source Finalized: 483, Received Messages: { rewarded: 42, messages-relayer-account: [43] }
Source Chain ->> Messages Relayer: Read Proof of Message 44 and Proof of Message 43 reward at Block 483
Messages Relayer ->> Target Chain: Submit Proof of Message 44 and Proof of Message 43 reward at Block 483
Target Chain ->> Target Chain: Import and Finalize Block 64
Note left of Target Chain: Finalized: 64, Source Finalized: 483, Received Messages: { rewarded: 43, messages-relayer-account: [44] }
</div>
<script src="https://cdn.jsdelivr.net/npm/mermaid@8.8.4/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad: true})</script>
</body>
</html>
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Parachains Finality Relay</title>
</head>
<body>
<h1>Parachains Finality Relay</h1>
<p>
Source Relay Chain is running GRANDPA Finality Gadget. Source Parachain is a parachain of the Source
Relay Chain. Bridge GRANDPA finality pallet is deployed at Target Chain runtime and is "connected"
to the Source Relay Chain. Bridge Parachains finality pallet is deployed at Target Chain and is
configured to track the Source Parachain. GRANDPA Relayer is configured to relay Source Relay Chain
finality to Target Chain. Parachains Relayer is configured to relay Source Parachain headers finality
to Target Chain.
</p>
<div class="mermaid">
sequenceDiagram
participant Source Parachain
participant Source Relay Chain
participant GRANDPA Relayer
participant Parachains Relayer
participant Target Chain
Note left of Source Parachain: Best: 125
Note left of Source Relay Chain: Finalized: 500, Best Parachain at Finalized: 120
Note right of Target Chain: Best Relay: 480, Best Parachain: 110
Source Parachain ->> Source Parachain: Import Block 126
Source Parachain ->> Source Relay Chain: Receives the Parachain block 126
Source Relay Chain ->> Source Relay Chain: Import block 501
Source Relay Chain ->> Source Relay Chain: Finalize block 501
Note left of Source Relay Chain: Finalized: 501, Best Parachain at Finalized: 126
Source Relay Chain ->> Parachains Relayer: notes new Source Parachain Block 126
Note left of Parachains Relayer: can't relay Source Parachain Block 126, because it requires at least Source Relay Block 501 at Target Chain
Source Relay Chain ->> Source Relay Chain: Import block 502
Source Relay Chain ->> Source Relay Chain: Finalize block 502
Source Relay Chain ->> GRANDPA Relayer: read GRANDPA Finality Proof of Block 502
GRANDPA Relayer ->> Target Chain: submit GRANDPA Finality Proof of Block 502
Note right of Target Chain: Best Relay: 502, Best Parachain: 110
Target Chain ->> Parachains Relayer: notes finalized Source Relay Block 502 at Target Chain
Source Relay Chain ->> Parachains Relayer: read Parachain Finality Proof at Relay Block 502
Parachains Relayer ->> Target Chain: submit Parachain Finality Proof at Relay Block 502
Note right of Target Chain: Best Relay: 502, Best Parachain: 126
</div>
<script src="https://cdn.jsdelivr.net/npm/mermaid@8.8.4/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad: true})</script>
</body>
</html>
@@ -0,0 +1,132 @@
# Polkadot <> Kusama Bridge Overview
This document describes how we use all components, described in the [High-Level Bridge Documentation](./high-level-overview.md),
to build the XCM bridge between Kusama and Polkadot. In this case, our 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).
## Bridge Hubs
All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains.
That's why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama
Bridge Hub under Kusama consensus.
The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to
use 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 runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs.
## Connecting Parachains
You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need
to use other parachains transactions, which will use HRMP to deliver message to the Bridge Hub. The Bridge Hub will
just queue this messages in its outbound lane, which is dedicated to deliver messages between two parachains.
Our first planned bridge will connect the Polkadot' Statemint and Kusama' Statemine. Bridge between those two
parachains would allow Statemint accounts to hold wrapped KSM tokens and Statemine accounts to hold wrapped DOT
tokens.
For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later,
when other parachains will join the bridge, they will be using other lanes for their messages.
## Running Relayers
We are planning to run our own complex relayer for the lane 00000000. The relayer will relay Kusama/Polkadot GRANDPA
justifications to the bridge hubs at the other side. It'll also relay finalized Kusama Bridge Hub and Polkadot Bridge
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.
We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost.
Apart from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have
a mechanism for rewarding relayers.
### Compensating the Cost of Message Delivery Transactions
One part of our rewarding scheme is that the cost of message delivery, for honest relayer, is zero. The honest relayer
is the relayer, which is following our rules:
- we do not reward relayers for submitting GRANDPA finality transactions. The only exception is submitting mandatory
headers (headers which are changing the GRANDPA authorities set) - the cost of such transaction is zero. The relayer
will pay the full cost for submitting all other headers;
- we do not reward relayers for submitting parachain finality transactions. The relayer will pay the full cost for
submitting parachain finality transactions;
- 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
messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then
the relayer 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
[`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
to prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they
are not 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
compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer
may 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.
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,
in the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section.
### Message Delivery Confirmation Rewards
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
Hub.;
- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms
delivery of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It
receives some fee 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.
### Who is Rewarding Relayers
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
of the bridge to cover relayer rewards.
Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Statemine (Kusama Parachain) will
have an account at the Polkadot Bridge Hub. The Statemint (Polkadot Parachain) will have an account at the Kusama
Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the
`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.
Statemine will only reward relayers that are delivering messages from Statemine. The Statemine sovereign account
is not used to cover rewards of bridging with some other Polkadot Parachain.
### Multiple Relayers and Rewards
Our goal is to incentivize running honest relayers. But we have no relayers sets, so at any time anyone may submit
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
special means, the cost of first included transacton 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
may be 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)
and [RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are
preventing 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 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,
the transaction is not rejected;
- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new,
the transaction is not rejected;
- [`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
[Compensating the Cost of Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions)
are applied.
+67
View File
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Polkadot &lt;&gt; Kusama Bridge</title>
</head>
<body>
<h1>Polkadot &lt;&gt; Kusama Bridge</h1>
<p>
Our bridge connects two parachains - Kusama Bridge Hub and Polkadot Bridge Hub. Messages that
are sent over bridge have XCM format and we are using existing architecture to dispatch them.
Since both Polkadot, Kusama and their parachains already have means to exchange XCM messages
within the same consensus system (HRMP, VMP, ...), it means that we are able to connect all those
chains with our bridge.
</p>
<p>
In our architecture, the lane that is used to relay messages over the bridge is determined by
the XCM source and destinations. So e.g. bridge between Statemint and Statemine (and opposite direction)
will use the lane 00000000, bridge between some other Polkadot Parachain and some other Kusama Parachain
will use the lane 00000001 and so on.
</p>
<div class="mermaid">
flowchart LR
subgraph Polkadot Consensus
polkadot(((Polkadot)))
statemint(((Statemint)))
polkadot_bh(((Polkadot Bridge Hub)))
polkadot---statemint
polkadot---polkadot_bh
statemint-->|Send Message Using HRMP|polkadot_bh
polkadot_bh-->|Send Message Using HRMP|statemint
statemint-->|Dispatch the Message|statemint
end
subgraph Kusama Consensus
kusama_bh(((Kusama Bridge Hub)))
statemine(((Statemine)))
kusama(((Kusama)))
kusama---statemine
kusama---kusama_bh
kusama_bh-->|Send Message Using HRMP|statemine
statemine-->|Dispatch the Message|statemine
statemine-->|Send Message Using HRMP|kusama_bh
end
polkadot_bh&lt;===&gt;|Message is relayed to the Bridged Chain using lane 00000000|kusama_bh
linkStyle 2 stroke:red
linkStyle 7 stroke:red
linkStyle 8 stroke:red
linkStyle 3 stroke:green
linkStyle 4 stroke:green
linkStyle 9 stroke:green
</div>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>