diff --git a/bridges/README.md b/bridges/README.md
index d45b328b2bdfe72f273235033feca548eed07b09..b588502642622b67853f7861efba7950a785bb32 100644
--- a/bridges/README.md
+++ b/bridges/README.md
@@ -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
diff --git a/bridges/docs/complex-relay.html b/bridges/docs/complex-relay.html
new file mode 100644
index 0000000000000000000000000000000000000000..21524bfd04913c108372fe65e006b67a94fc4d31
--- /dev/null
+++ b/bridges/docs/complex-relay.html
@@ -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>
diff --git a/bridges/docs/grandpa-finality-relay.html b/bridges/docs/grandpa-finality-relay.html
new file mode 100644
index 0000000000000000000000000000000000000000..4136621b1a4bf6ebc0f9f675dc900fd12457bbae
--- /dev/null
+++ b/bridges/docs/grandpa-finality-relay.html
@@ -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>
diff --git a/bridges/docs/high-level-overview.md b/bridges/docs/high-level-overview.md
index 2642c20c86abbc723f385d96b1f02e8179020f12..2c174dbc98a4cec6d654ac696821768a44c8004a 100644
--- a/bridges/docs/high-level-overview.md
+++ b/bridges/docs/high-level-overview.md
@@ -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.
+
+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.
+
+## Terminology
+
+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 has both on-chain (pallets) and offchain (relayers) components.
+
+## On-chain components
 
-## Overview
+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.
 
-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.
+### Bridge GRANDPA Finality Pallet
 
-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.
+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.
 
-The bridge is built from various components. Here is a quick overview of the important ones.
+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.
 
-### Header Sync
+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).
 
-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.
+More: [code](../modules/grandpa/).
 
-### Headers Relayer
+### Bridge Parachains Finality Pallet
 
-A standalone application connected to both chains. It submits every source chain header it sees to
-the target chain through RPC.
+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.
 
-### Message Delivery
+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.
 
-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 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.
 
-### Message Dispatch
+More: [code](../modules/parachains/).
 
-A FRAME pallet responsible for interpreting the payload of delivered messages.
+### Bridge Messages Pallet
 
-### Message Relayer
+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.
 
-A standalone application handling delivery of the messages from source chain to the target chain.
+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.
 
-## Processes
+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.
 
-High level sequence charts of the process can be found in [a separate document](./high-level.html).
+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.
 
-### Substrate (GRANDPA) Header Sync
+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.
 
-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.
+More: [code](../modules/messages/).
 
-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.
+### Bridge Relayers Pallet
 
-Referer to the [pallet documentation](../modules/grandpa/src/lib.rs) for more details.
+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.
 
-#### Header Relayer strategy
+More: [code](../modules/relayers/).
 
-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.
+## Offchain Components
 
-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.
+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.
 
-### Message Passing
+### GRANDPA Finality Relay
 
-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 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.
 
-#### Message Lanes Delivery
+More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [code](../relays/finality/).
 
-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.
+### Parachains Finality Relay
 
-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 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.
 
-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.
+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. 
 
-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.
+More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/).
 
-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.
+### Messages Relay
 
-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.
+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.
 
-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).
+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.
 
-#### Dispatching Messages
+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.
 
-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.
+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.
 
-An example `Call` of the target chain would look something like this:
+More: [Messages Relay Sequence Diagram](./messages-relay.html), [code](../relays/messages/).
 
-```rust
-target_runtime::Call::Balances(target_runtime::pallet_balances::Call::transfer(recipient, amount))
-```
+### Complex Relay
 
-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.
+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.
 
-When dispatching messages there are three Origins which can be used by the target chain:
-1. Root Origin
-2. Source Origin
-3. Target Origin
+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.
 
-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 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.
 
-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
+More: [Complex Relay Sequence Diagram](./complex-relay.html), [code](../relays/bin-substrate/src/cli/relay_headers_and_messages/).
diff --git a/bridges/docs/messages-relay.html b/bridges/docs/messages-relay.html
new file mode 100644
index 0000000000000000000000000000000000000000..c4dab9901e03bc704d4e5241d343331b76731c2c
--- /dev/null
+++ b/bridges/docs/messages-relay.html
@@ -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>
diff --git a/bridges/docs/parachains-finality-relay.html b/bridges/docs/parachains-finality-relay.html
new file mode 100644
index 0000000000000000000000000000000000000000..4fc1392b87dea73cd49cff8fc6ccfe2125d5994a
--- /dev/null
+++ b/bridges/docs/parachains-finality-relay.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>
diff --git a/bridges/docs/polkadot-kusama-bridge-overview.md b/bridges/docs/polkadot-kusama-bridge-overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..302196718b9829fee16a986cc416bf3c2658eb96
--- /dev/null
+++ b/bridges/docs/polkadot-kusama-bridge-overview.md
@@ -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.
diff --git a/bridges/docs/polkadot-kusama-bridge.html b/bridges/docs/polkadot-kusama-bridge.html
new file mode 100644
index 0000000000000000000000000000000000000000..dcbae0e7b176904514a217daebc9ce7b7a5e733f
--- /dev/null
+++ b/bridges/docs/polkadot-kusama-bridge.html
@@ -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>
\ No newline at end of file