Squashed 'bridges/' content from commit 062554430

git-subtree-dir: bridges
git-subtree-split: 0625544309ff299307f7e110f252f04eac383102
This commit is contained in:
Branislav Kontur
2022-12-01 22:32:52 +01:00
commit d2b7ee2575
357 changed files with 79920 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
# High-Level Bridge Documentation
## Purpose
Trustless connecting between two Substrate-based chains using GRANDPA finality.
## Overview
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.
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.
The bridge is built from various components. Here is a quick overview of the important ones.
### Header Sync
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.
### Headers Relayer
A standalone application connected to both chains. It submits every source chain header it sees to
the target chain through RPC.
### Message Delivery
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.
### Message Dispatch
A FRAME pallet responsible for interpreting the payload of delivered messages.
### Message Relayer
A standalone application handling delivery of the messages from source chain to the target chain.
## Processes
High level sequence charts of the process can be found in [a separate document](./high-level.html).
### Substrate (GRANDPA) Header Sync
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 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.
Referer to the [pallet documentation](../modules/grandpa/src/lib.rs) for more details.
#### Header Relayer strategy
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.
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.
### Message Passing
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.
#### Message Lanes Delivery
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.
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.
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.
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.
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.
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.
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).
#### Dispatching Messages
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.
An example `Call` of the target chain would look something like this:
```rust
target_runtime::Call::Balances(target_runtime::pallet_balances::Call::transfer(recipient, amount))
```
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.
When dispatching messages there are three Origins which can be used by the target chain:
1. Root Origin
2. Source Origin
3. Target Origin
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.
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.
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.
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.
See [`CallOrigin` documentation](../primitives/message-dispatch/src/lib.rs) for more details.
#### Message Relayers Strategy
+55
View File
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>High Level Bridge Components</title>
</head>
<body>
<h1>Header Sync</h1>
<p>Header pallet on the target chain, keeps track of the forks, but requires finality for blocks that perform authority set changes. That means, it won't sync a fork with authority set change unless that change finalized.</p>
<div class="mermaid">
sequenceDiagram
participant Source Chain
participant Relayer
participant Target Chain
Note right of Target Chain: Best: 0, Finalized: 0
Source Chain ->> Source Chain: Import Block 1
Source Chain ->> Source Chain: Import Block 2
Relayer ->> Target Chain: Submit Block 1
Note right of Target Chain: Best: 1, Finalized: 0
Relayer ->> Target Chain: Submit Block 2
Note right of Target Chain: Best: 2, Finalized: 0
Source Chain ->> Source Chain: Import Block 2'
Relayer ->> Target Chain: Submit Block 2'
Note right of Target Chain: Best: 2 or 2', Finalized: 0
Source Chain ->> Source Chain: Finalize Block 2'
Relayer ->> Target Chain: Submit Finality of Block 2'
Note right of Target Chain: Best: 2', Finalized: 2'
</div>
<h1>Message Delivery (single lane)</h1>
<p>Pending messages are stored on-chain (source) so the relayer code is completely stateless - it can read all the details from the chain.</p>
<p>Delivering pending messages requires finality first.</p>
<div class="mermaid">
sequenceDiagram
participant Source Chain
participant Relayer
participant Target Chain
Source Chain ->> Source Chain: Queue Message 1
Source Chain ->> Source Chain: Queue Message 2
Source Chain ->> Source Chain: Queue Message 3
Note left of Source Chain: Queued Messages: [1, 2, 3, ]
Note left of Source Chain: Reward for [1, 2, 3, ] reserved
Relayer ->> Target Chain: Deliver Messages 1..2
Note right of Target Chain: Target chain dispatches the messages.<br> To Confirm: {1..2 => relayer_1}
Relayer ->> Source Chain: Delivery Confirmation of 1..2
Note left of Source Chain: Queued Messages: [3, ]
Note left of Source Chain: Reward payout for [1, 2, ]
Relayer -->> Target Chain: Confirmed Messages 1..2
Note right of Target Chain: To Confirm: {}
Note over Relayer, Target Chain: (this is not a separate transaction, <br >it's bundled with the "Deliver Messages" proof)
</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>
+22
View File
@@ -0,0 +1,22 @@
Plan for the Internal Audit:
1. High-level overview (describing layers, maybe with pictures)
- what have we done already.
[Tomek to present]
[Hernando to help with diagrams today]
2. Demo? How to play with the network.
[Hernando]
3. Demo of token transfer on Millau.
[Hernando]
4. Go through the scenario description and let people ask questions in the meantime.
Jump to the code on demand.
[Tomek, Hernando, Slava]
...
5. The roadmap
- outstanding issues.
[Tomek]
+47
View File
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Flow Chart of Millau to Rialto Transfer</title>
</head>
<body>
<h1>Scenario: <code>mDave</code> sending RLT to <code>rEve</code></h1>
<div class="mermaid">
sequenceDiagram
participant mDave
participant Millau
participant Bridge Relayer
participant Rialto
participant rEve
Rialto->>Rialto: Endow r(mDave) with RLT.
mDave->>Millau: send_message(transfer, 5 RLT, rEve)
Millau->>Millau: Locks fee &amp; reward for the relayer and queues the message.
rect rgb(205, 226, 244)
Bridge Relayer->>+Millau: What's your best header?
Millau-->>-Bridge Relayer: It's header 5.
Bridge Relayer->>+Rialto: What's the best Millau header you know about?
Rialto-->>-Bridge Relayer: I only know about 4.
Bridge Relayer->>Rialto: Cool, here is Millau header 5 [`submit_signed_header()`].
Bridge Relayer->>+Rialto: What's the best finalized Millau header you know about?
Rialto-->>-Bridge Relayer: I only know about 3.
Bridge Relayer->>+Millau: Do you have a finality proof for 4..5?
Millau-->>-Bridge Relayer: Yes I do, here it is.
Bridge Relayer->>Rialto: Here is the finality proof for 5 [`finalize_header()`].
end
rect rgb(218, 195, 244)
Bridge Relayer->>+Millau: Do you have any messages for me to deliver (at 5)?
Millau-->>-Bridge Relayer: Yes, here they are.
Bridge Relayer->>+Rialto: I have some new messages for you [`receive_messages_proof()`].
Rialto->>Rialto: Validate and Dispatch Message.
Rialto->>rEve: Transfer(5 RLT) from r(mDave).
Rialto-->>-Bridge Relayer: Event(Message Succesfully Dispatched).
Bridge Relayer->>Millau: I sent your message, can I get paid now [`receive_messages_delivery_proof`]?
Millau-->>Bridge Relayer: Yes, here you go $$$.
Bridge Relayer ->>Rialto: These messages are confirmed now, feel free to clean up.
end
</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>
+131
View File
@@ -0,0 +1,131 @@
# How to send messages
The Substrate-to-Substrate relay comes with a command line interface (CLI) which is implemented
by the `substrate-relay` binary.
```
Substrate-to-Substrate relay
USAGE:
substrate-relay <SUBCOMMAND>
FLAGS:
-h, --help
Prints help information
-V, --version
Prints version information
SUBCOMMANDS:
help Prints this message or the help of the given subcommand(s)
init-bridge Initialize on-chain bridge pallet with current header data
relay-headers Start headers relay between two chains
relay-messages Start messages relay between two chains
send-message Send custom message over the bridge
```
The relay related commands `relay-headers` and `relay-messages` are basically continously running a
sync loop between the `Millau` and `Rialto` chains. The `init-bridge` command submitts initialization
transactions. An initialization transaction brings an initial header and authorities set from a source
chain to a target chain. The header synchronization then starts from that header.
For sending custom messages over an avialable bridge, the `send-message` command is used.
```
Send custom message over the bridge.
Allows interacting with the bridge by sending messages over `Messages` component. The message is being sent to the
source chain, delivered to the target chain and dispatched there.
USAGE:
substrate-relay send-message <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
SUBCOMMANDS:
help Prints this message or the help of the given subcommand(s)
millau-to-rialto Submit message to given Millau -> Rialto lane
rialto-to-millau Submit message to given Rialto -> Millau lane
```
Messages are send from a source chain to a target chain using a so called `message lane`. Message lanes handle
both, message transport and message dispatch. There is one command for submitting a message to each of the two
available bridges, namely `millau-to-rialto` and `rialto-to-millau`.
Submitting a message requires a number of arguments to be provided. Those arguments are essentially the same
for both submit message commands, hence only the output for `millau-to-rialto` is shown below.
```
Submit message to given Millau -> Rialto lane
USAGE:
substrate-relay send-message millau-to-rialto [OPTIONS] --lane <lane> --source-host <source-host> --source-port <source-port> --source-signer <source-signer> --origin <origin> --target-signer <target-signer> <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
--fee <fee>
Delivery and dispatch fee. If not passed, determined automatically
--lane <lane> Hex-encoded lane id
--source-host <source-host> Connect to Source node at given host
--source-port <source-port> Connect to Source node websocket server at given port
--source-signer <source-signer>
The SURI of secret key to use when transactions are submitted to the Source node
--source-signer-password <source-signer-password>
The password for the SURI of secret key to use when transactions are submitted to the Source node
--origin <origin>
The origin to use when dispatching the message on the target chain [possible values: Target, Source]
--target-signer <target-signer>
The SURI of secret key to use when transactions are submitted to the Target node
--target-signer-password <target-signer-password>
The password for the SURI of secret key to use when transactions are submitted to the Target node
SUBCOMMANDS:
help Prints this message or the help of the given subcommand(s)
remark Make an on-chain remark (comment)
transfer Transfer the specified `amount` of native tokens to a particular `recipient`
```
As can be seen from the output, there are two types of messages available: `remark` and `transfer`.
A remark is some opaque message which will be placed on-chain. For basic testing, a remark is
the easiest to go with.
Usage of the arguments is best explained with an example. Below you can see, how a remark
would look like:
```
substrate-relay send-message millau-to-rialto \
--source-host=127.0.0.1 \
--source-port=10946 \
--source-signer=//Dave \
--target-signer=//Dave \
--lane=00000000 \
--origin Target \
remark
```
Messages are basically regular transactions. That means, they have to be signed. In order
to send a message, you have to control an account private key on both, the source and
the target chain. Those accounts are specified using the `--source-signer` and `--target-signer`
arguments in the example above.
Message delivery and dispatch requires a fee to be paid. In the example above, we have not
specified the `--fee` argument. Hence, the fee will be estimated automatically. Note that
in order to pay the fee, the message sender account has to have sufficient funds available.
The `--origin` argument allows to denote under which authority the message will be dispatched
on the target chain. Accepted values are `Target` and `Source`.
Although not strictly necessary, it is recommended, to use one of the well-known development
accounts (`Alice`, `Bob`, `Charlie`, `Dave`, `Eve`) for message sending. Those accounts are
endowed with funds for fee payment. In addtion, the development `Seed URI` syntax
(like `//Dave`) for the signer can be used, which will remove the need for a password.
+221
View File
@@ -0,0 +1,221 @@
# Testing Scenarios
In the scenarios, for simplicity, we call the chains Kusama (KSM token) and Polkadot (DOT token),
but they should be applicable to any other chains. The first scenario has detailed description about
the entire process (also see the [sequence diagram](./scenario1.html)). Other scenarios only contain
a simplified interaction focusing on things that are unique for that particular scenario.
Notation:
- kX - user X interacting with Kusama chain.
- `k(kX)` - Kusama account id of user kX (native account id; usable on Kusama)
- `p(kX)` - Polkadot account id of user kX (account id derived from `k(kX)` usable on Polkadot)
- [Kusama] ... - Interaction happens on Kusama (e.g. the user interacts with Kusama chain)
- [Polkadot] ... - Interaction happens on Polkadot
Basic Scenarios
===========================
Scenario 1: Kusama's Alice receiving & spending DOTs
---------------------------
Kusama's Alice (kAlice) receives 5 DOTs from Polkadot's Bob (pBob) and sends half of them to
kCharlie.
1. Generate kAlice's DOT address (`p(kAlice)`).
See function:
```rust
bp_runtime::derive_account_id(b"pdot", kAlice)
```
or:
```rust
let hash = bp_polkadot::derive_kusama_account_id(kAlice);
let p_kAlice = bp_polkadot::AccountIdConverter::convert(hash);
```
2. [Polkadot] pBob transfers 5 DOTs to `p(kAlice)`
1. Creates & Signs a transaction with `Call::Transfer(..)`
1. It is included in block.
1. kAlice observers Polkadot chain to see her balance at `p(kAlice)` updated.
3. [Kusama] kAlice sends 2.5 DOTs to `p(kCharlie)`
1. kAlice prepares:
```rust
let call = polkadot::Call::Balances(polkadot::Balances::Transfer(p(kCharlie), 2.5DOT)).encode();
let weight = call.get_dispatch_info().weight;
```
1. kAlice prepares Kusama transaction:
```rust
kusama::Call::Messages::<Instance=Polkadot>::send_message(
// dot-transfer-lane (truncated to 4bytes)
lane_id,
payload: MessagePayload {
// Get from current polkadot runtime (kind of hardcoded)
spec_version: 1,
// kAlice should know the exact dispatch weight of the call on the target
// source verifies: at least to cover call.length() and below max weight
weight,
// simply bytes, we don't know anything about that on the source chain
call,
// origin that should be used during dispatch on the target chain
origin: CallOrigin::SourceAccount(kAlice),
},
delivery_and_dispatch_fee: {
(single_message_delivery_weight
// source weight = X * target weight
+ convert_target_weight_to_source_weight(weight)
+ confirmation_transaction_weight
)
// This uses an on-chain oracle to convert weights of the target chain to source fee
* weight_to_fee
// additional reward for the relayer (pallet parameter)
+ relayers_fee
},
)
```
1. [Kusama] kAlice sends Kusama transaction with the above `Call` and pays regular fees. The
dispatch additionally reservers target-chain delivery and dispatch fees (including relayer's
reward).
4. [Kusama] kAlice's transaction is included in block `B1`
### Syncing headers loop
5. Relayer sees that `B1` has not yet been delivered to the target chain.
[Sync loop code](https://github.com/paritytech/parity-bridges-common/blob/8b327a94595c4a6fae6d7866e24ecf2390501e32/relays/headers-relay/src/sync_loop.rs#L199).
1. Relayer prepares transaction which delivers `B1` and with all of the missing
ancestors to the target chain (one header per transaction).
1. After the transaction is succesfully dispatched the Polkadot on-chain light client of the Kusama
chain learns about block `B1` - it is stored in the on-chain storage.
### Syncing finality loop
8. Relayer is subscribed to finality events on Kusama. Relayer gets a finality notification for
block `B3`.
1. The header sync informs the target chain about `B1..B3` blocks (see point 6).
1. Relayer learns about missing finalization of `B1..B3` on the target chain, see
[finality maintenance code](https://github.com/paritytech/parity-bridges-common/blob/8b327a94595c4a6fae6d7866e24ecf2390501e32/relays/substrate/src/headers_maintain.rs#L107).
1. Relayer submits justification for `B3` to the target chain (`finalize_header`).
See [#421](https://github.com/paritytech/parity-bridges-common/issues/421) for multiple
authority set changes support in Relayer (i.e. what block the target chain expects, not only
what I have).
Relayer is doing two things:
- syncing on demand (what blocks miss finality)
- and syncing as notifications are received (recently finalized on-chain)
1. Eventually Polkadot on-chain light client of Kusama learns about finality of `B1`.
### Syncing messages loop
13. The relayer checks the on-chain storage (last finalized header on the source, best header on the
target):
- Kusama outbound lane
- Polkadot inbound lane
Lanes contains `latest_generated_nonce` and `latest_received_nonce` respectively. The relayer
syncs messages between that range.
1. The relayer gets a proof for every message in that range (using the RPC of messages module)
1. The relayer creates a message delivery transaction (but it has weight, size, and count limits).
The count limit is there to make the loop of delivery code bounded.
```rust
receive_message_proof(
relayer_id, // account id of the source chain
proof, // messages + proofs (hash of source block `B1`, nonces, lane_id + storage proof)
dispatch_weight // relayer declares how much it will take to dispatch all messages in that transaction,
)
```
The `proof` can also contain an update of outbound lane state of source chain, which indicates
the delivery confirmation of these messages and reward payment, so that the target chain can
truncate its unpayed rewards vector.
The target chain stores `relayer_ids` that delivered messages because the relayer can generate
a storage proof to show that they did indeed deliver those messages. The reward is paid on the
source chain and we inform the target chain about that fact so it can prune these `relayer_ids`.
It's totally fine if there are no messages, and we only include the reward payment proof
when calling that function.
1. 🥳 the message is now delivered and dispatched on the target chain!
1. The relayer now needs to confirm the delivery to claim her payment and reward on the source
chain.
1. The relayer creates a transaction on the source chain with call:
```rust
receive_messages_delivery_proof(
proof, // hash of the finalized target chain block, lane_id, storage proof
)
```
### UI challenges
- The UI should warn before (or prevent) sending to `k(kCharlie)`!
Scenario 2: Kusama's Alice nominating validators with her DOTs
---------------------------
kAlice receives 10 DOTs from pBob and nominates `p(pCharlie)` and `p(pDave)`.
1. Generate kAlice's DOT address (`p(kAlice)`)
2. [Polkadot] pBob transfers 5 DOTs to `p(kAlice)`
3. [Kusama] kAlice sends a batch transaction:
- `staking::Bond` transaction to create stash account choosing `p(kAlice)` as the controller account.
- `staking::Nominate(vec![p(pCharlie)])` to nominate pCharlie using the controller account.
Scenario 3: Kusama Treasury receiving & spending DOTs
---------------------------
pBob sends 15 DOTs to Kusama Treasury which Kusama Governance decides to transfer to kCharlie.
1. Generate source account for the treasury (`kTreasury`).
2. [Polkadot] pBob tarnsfers 15 DOTs to `p(kTreasury)`.
2. [Kusama] Send a governance proposal to send a bridge message which transfers funds to `p(kCharlie)`.
3. [Kusama] Dispatch the governance proposal using `kTreasury` account id.
Extra scenarios
===========================
Scenario 4: Kusama's Alice setting up 1-of-2 multi-sig to spend from either Kusama or Polkadot
---------------------------
Assuming `p(pAlice)` has at least 7 DOTs already.
1. Generate multisig account id: `pMultiSig = multi_account_id(&[p(kAlice), p(pAlice)], 1)`.
2. [Kusama] Transfer 7 DOTs to `pMultiSig` using `TargetAccount` origin of `pAlice`.
3. [Kusama] Transfer 2 DOTs to `p(kAlice)` from the multisig:
- Send `multisig::as_multi_threshold_1(vec![p(pAlice)], balances::Transfer(p(kAlice), 2))`
Scenario 5: Kusama Treasury staking & nominating validators with DOTs
---------------------------
Scenario 6: Kusama Treasury voting in Polkadot's democracy proposal
---------------------------
Potentially interesting scenarios
===========================
Scenario 7: Polkadot's Bob spending his DOTs by using Kusama chain
---------------------------
We can assume he holds KSM. Problem: he can pay fees, but can't really send (sign) a transaction?
Shall we support some kind of dispatcher?
Scenario 8: Kusama Governance taking over Kusama's Alice DOT holdings
---------------------------
We use `SourceRoot` call to transfer her's DOTs to Kusama treasury. Source chain root
should also be able to send messages as `CallOrigin::SourceAccount(Alice)` though.