From 9b57f2181cd26529870d90a61c3e728667c89e65 Mon Sep 17 00:00:00 2001
From: Svyatoslav Nikolsky <svyatonik@gmail.com>
Date: Mon, 20 Mar 2023 17:49:48 +0300
Subject: [PATCH] Kusama <> Polkadot relay prototype (#1982)

* moved bridge declarations to dedicated folder

* Kusama <> Polkadot bridges declaration

* support for Kusama <> Polkadot bridge in CLI

* update dictionary
---
 .../chain-bridge-hub-kusama/Cargo.toml        |  31 ++++
 .../chain-bridge-hub-kusama/src/lib.rs        |  84 +++++++++
 .../chain-bridge-hub-polkadot/Cargo.toml      |  32 ++++
 .../chain-bridge-hub-polkadot/src/lib.rs      |  75 ++++++++
 bridges/primitives/chain-kusama/src/lib.rs    |   3 +
 bridges/primitives/chain-polkadot/src/lib.rs  |   3 +
 bridges/primitives/runtime/src/lib.rs         |  71 ++------
 bridges/relays/bin-substrate/Cargo.toml       |   4 +
 ..._kusama_messages_to_bridge_hub_polkadot.rs |  65 +++++++
 ..._polkadot_messages_to_bridge_hub_kusama.rs |  65 +++++++
 .../kusama_headers_to_bridge_hub_polkadot.rs  |  72 ++++++++
 ...usama_parachains_to_bridge_hub_polkadot.rs |  75 ++++++++
 .../src/bridges/kusama_polkadot/mod.rs        |  24 +++
 .../polkadot_headers_to_bridge_hub_kusama.rs  |  72 ++++++++
 ...olkadot_parachains_to_bridge_hub_kusama.rs |  75 ++++++++
 .../relays/bin-substrate/src/bridges/mod.rs   |  23 +++
 .../millau_headers_to_rialto.rs               |   3 +-
 .../millau_messages_to_rialto.rs              |   0
 .../src/bridges/rialto_millau/mod.rs          |  22 +++
 .../rialto_headers_to_millau.rs               |   3 +-
 .../rialto_messages_to_millau.rs              |   0
 .../millau_headers_to_rialto_parachain.rs     |   2 +-
 .../millau_messages_to_rialto_parachain.rs    |   0
 .../bridges/rialto_parachain_millau/mod.rs    |  22 +++
 .../rialto_parachain_messages_to_millau.rs    |   0
 .../rialto_parachains_to_millau.rs            |   5 +-
 ...ub_rococo_messages_to_bridge_hub_wococo.rs |   0
 ...ub_wococo_messages_to_bridge_hub_rococo.rs |   0
 .../src/bridges/rococo_wococo/mod.rs          |  24 +++
 .../rococo_headers_to_bridge_hub_wococo.rs    |   0
 .../rococo_parachains_to_bridge_hub_wococo.rs |   4 +-
 .../wococo_headers_to_bridge_hub_rococo.rs    |   0
 .../wococo_parachains_to_bridge_hub_rococo.rs |   4 +-
 .../src/bridges/westend_millau/mod.rs         |  20 +++
 .../westend_headers_to_millau.rs              |   0
 .../westend_parachains_to_millau.rs           |   3 +-
 .../relays/bin-substrate/src/chains/kusama.rs |  32 ++++
 .../relays/bin-substrate/src/chains/mod.rs    |  19 +-
 .../bin-substrate/src/chains/polkadot.rs      |  32 ++++
 .../relays/bin-substrate/src/cli/bridge.rs    |   7 +-
 .../bin-substrate/src/cli/init_bridge.rs      |  18 +-
 .../bin-substrate/src/cli/relay_headers.rs    |  30 +++-
 .../src/cli/relay_headers_and_messages/mod.rs |  20 ++-
 .../bin-substrate/src/cli/relay_messages.rs   |  30 +++-
 .../bin-substrate/src/cli/relay_parachains.rs |  46 +++--
 .../bin-substrate/src/cli/send_message.rs     |  20 ++-
 bridges/relays/bin-substrate/src/main.rs      |   1 +
 .../client-bridge-hub-kusama/Cargo.toml       |  28 +++
 .../client-bridge-hub-kusama/src/lib.rs       | 162 ++++++++++++++++++
 .../src/runtime_wrapper.rs                    |  74 ++++++++
 .../client-bridge-hub-polkadot/Cargo.toml     |  32 ++++
 .../client-bridge-hub-polkadot/src/lib.rs     | 160 +++++++++++++++++
 .../src/runtime_wrapper.rs                    | 119 +++++++++++++
 .../client-bridge-hub-rococo/src/lib.rs       |   1 -
 .../client-bridge-hub-wococo/src/lib.rs       |   1 -
 bridges/relays/client-kusama/src/lib.rs       |  13 +-
 bridges/relays/client-millau/src/lib.rs       |   2 -
 bridges/relays/client-polkadot/src/lib.rs     |  13 +-
 .../relays/client-rialto-parachain/src/lib.rs |   2 -
 bridges/relays/client-rialto/src/lib.rs       |   2 -
 bridges/relays/client-rococo/src/lib.rs       |   1 -
 bridges/relays/client-substrate/src/chain.rs  |   5 -
 .../relays/client-substrate/src/test_chain.rs |   2 -
 bridges/relays/client-westend/src/lib.rs      |   2 -
 bridges/relays/client-wococo/src/lib.rs       |   1 -
 65 files changed, 1600 insertions(+), 161 deletions(-)
 create mode 100644 bridges/primitives/chain-bridge-hub-kusama/Cargo.toml
 create mode 100644 bridges/primitives/chain-bridge-hub-kusama/src/lib.rs
 create mode 100644 bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml
 create mode 100644 bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs
 create mode 100644 bridges/relays/bin-substrate/src/bridges/mod.rs
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_millau}/millau_headers_to_rialto.rs (94%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_millau}/millau_messages_to_rialto.rs (100%)
 create mode 100644 bridges/relays/bin-substrate/src/bridges/rialto_millau/mod.rs
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_millau}/rialto_headers_to_millau.rs (94%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_millau}/rialto_messages_to_millau.rs (100%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/millau_headers_to_rialto_parachain.rs (96%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/millau_messages_to_rialto_parachain.rs (100%)
 create mode 100644 bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/rialto_parachain_messages_to_millau.rs (100%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/rialto_parachains_to_millau.rs (91%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rococo_wococo}/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs (100%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rococo_wococo}/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs (100%)
 create mode 100644 bridges/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs
 rename bridges/relays/bin-substrate/src/{chains => bridges/rococo_wococo}/rococo_headers_to_bridge_hub_wococo.rs (100%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rococo_wococo}/rococo_parachains_to_bridge_hub_wococo.rs (92%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rococo_wococo}/wococo_headers_to_bridge_hub_rococo.rs (100%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/rococo_wococo}/wococo_parachains_to_bridge_hub_rococo.rs (92%)
 create mode 100644 bridges/relays/bin-substrate/src/bridges/westend_millau/mod.rs
 rename bridges/relays/bin-substrate/src/{chains => bridges/westend_millau}/westend_headers_to_millau.rs (100%)
 rename bridges/relays/bin-substrate/src/{chains => bridges/westend_millau}/westend_parachains_to_millau.rs (95%)
 create mode 100644 bridges/relays/bin-substrate/src/chains/kusama.rs
 create mode 100644 bridges/relays/bin-substrate/src/chains/polkadot.rs
 create mode 100644 bridges/relays/client-bridge-hub-kusama/Cargo.toml
 create mode 100644 bridges/relays/client-bridge-hub-kusama/src/lib.rs
 create mode 100644 bridges/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs
 create mode 100644 bridges/relays/client-bridge-hub-polkadot/Cargo.toml
 create mode 100644 bridges/relays/client-bridge-hub-polkadot/src/lib.rs
 create mode 100644 bridges/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs

diff --git a/bridges/primitives/chain-bridge-hub-kusama/Cargo.toml b/bridges/primitives/chain-bridge-hub-kusama/Cargo.toml
new file mode 100644
index 0000000000000..6d4334eaa57f0
--- /dev/null
+++ b/bridges/primitives/chain-bridge-hub-kusama/Cargo.toml
@@ -0,0 +1,31 @@
+[package]
+name = "bp-bridge-hub-kusama"
+description = "Primitives of BridgeHubRococo parachain runtime."
+version = "0.1.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2021"
+license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+
+[dependencies]
+# Bridge Dependencies
+
+bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false }
+bp-runtime = { path = "../../primitives/runtime", default-features = false }
+bp-messages = { path = "../../primitives/messages", default-features = false }
+
+# Substrate Based Dependencies
+
+frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+
+[features]
+default = ["std"]
+std = [
+	"bp-bridge-hub-cumulus/std",
+	"bp-messages/std",
+	"bp-runtime/std",
+	"frame-support/std",
+	"sp-api/std",
+	"sp-std/std",
+]
diff --git a/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs b/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs
new file mode 100644
index 0000000000000..6ca2cd047fb7e
--- /dev/null
+++ b/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs
@@ -0,0 +1,84 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Module with configuration which reflects BridgeHubKusama runtime setup (AccountId, Headers,
+//! Hashes...)
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use bp_bridge_hub_cumulus::*;
+use bp_messages::*;
+use bp_runtime::{
+	decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain,
+};
+use frame_support::{
+	dispatch::DispatchClass,
+	sp_runtime::{MultiAddress, MultiSigner},
+	RuntimeDebug,
+};
+use sp_std::prelude::*;
+
+/// BridgeHubKusama parachain.
+#[derive(RuntimeDebug)]
+pub struct BridgeHubKusama;
+
+impl Chain for BridgeHubKusama {
+	type BlockNumber = BlockNumber;
+	type Hash = Hash;
+	type Hasher = Hasher;
+	type Header = Header;
+
+	type AccountId = AccountId;
+	type Balance = Balance;
+	type Index = Index;
+	type Signature = Signature;
+
+	fn max_extrinsic_size() -> u32 {
+		*BlockLength::get().max.get(DispatchClass::Normal)
+	}
+
+	fn max_extrinsic_weight() -> Weight {
+		BlockWeights::get()
+			.get(DispatchClass::Normal)
+			.max_extrinsic
+			.unwrap_or(Weight::MAX)
+	}
+}
+
+impl Parachain for BridgeHubKusama {
+	const PARACHAIN_ID: u32 = BRIDGE_HUB_KUSAMA_PARACHAIN_ID;
+}
+
+/// Public key of the chain account that may be used to verify signatures.
+pub type AccountSigner = MultiSigner;
+
+/// The address format for describing accounts.
+pub type Address = MultiAddress<AccountId, ()>;
+
+/// Identifier of BridgeHubKusama in the Kusama relay chain.
+pub const BRIDGE_HUB_KUSAMA_PARACHAIN_ID: u32 = 1002;
+
+/// Name of the With-BridgeHubKusama messages pallet instance that is deployed at bridged chains.
+// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+pub const WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages";
+
+/// Name of the With-BridgeHubKusama bridge-relayers pallet instance that is deployed at bridged
+/// chains.
+// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+pub const WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME: &str = "BridgeRelayers";
+
+decl_bridge_finality_runtime_apis!(bridge_hub_kusama);
+decl_bridge_messages_runtime_apis!(bridge_hub_kusama);
diff --git a/bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml b/bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml
new file mode 100644
index 0000000000000..2a0ab3213c85b
--- /dev/null
+++ b/bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml
@@ -0,0 +1,32 @@
+[package]
+name = "bp-bridge-hub-polkadot"
+description = "Primitives of BridgeHubWococo parachain runtime."
+version = "0.1.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2021"
+license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+
+[dependencies]
+
+# Bridge Dependencies
+
+bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false }
+bp-runtime = { path = "../../primitives/runtime", default-features = false }
+bp-messages = { path = "../../primitives/messages", default-features = false }
+
+# Substrate Based Dependencies
+
+frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+
+[features]
+default = ["std"]
+std = [
+	"bp-bridge-hub-cumulus/std",
+	"bp-runtime/std",
+	"bp-messages/std",
+	"frame-support/std",
+	"sp-api/std",
+	"sp-std/std",
+]
diff --git a/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs b/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs
new file mode 100644
index 0000000000000..646fb0a6e4186
--- /dev/null
+++ b/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs
@@ -0,0 +1,75 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Module with configuration which reflects BridgeHubPolkadot runtime setup
+//! (AccountId, Headers, Hashes...)
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use bp_bridge_hub_cumulus::*;
+use bp_messages::*;
+use bp_runtime::{
+	decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain,
+};
+use frame_support::{dispatch::DispatchClass, RuntimeDebug};
+use sp_std::prelude::*;
+
+/// BridgeHubPolkadot parachain.
+#[derive(RuntimeDebug)]
+pub struct BridgeHubPolkadot;
+
+impl Chain for BridgeHubPolkadot {
+	type BlockNumber = BlockNumber;
+	type Hash = Hash;
+	type Hasher = Hasher;
+	type Header = Header;
+
+	type AccountId = AccountId;
+	type Balance = Balance;
+	type Index = Index;
+	type Signature = Signature;
+
+	fn max_extrinsic_size() -> u32 {
+		*BlockLength::get().max.get(DispatchClass::Normal)
+	}
+
+	fn max_extrinsic_weight() -> Weight {
+		BlockWeights::get()
+			.get(DispatchClass::Normal)
+			.max_extrinsic
+			.unwrap_or(Weight::MAX)
+	}
+}
+
+impl Parachain for BridgeHubPolkadot {
+	const PARACHAIN_ID: u32 = BRIDGE_HUB_POLKADOT_PARACHAIN_ID;
+}
+
+/// Identifier of BridgeHubPolkadot in the Polkadot relay chain.
+// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+pub const BRIDGE_HUB_POLKADOT_PARACHAIN_ID: u32 = 1002;
+
+/// Name of the With-BridgeHubPolkadot messages pallet instance that is deployed at bridged chains.
+// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+pub const WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages";
+
+/// Name of the With-BridgeHubPolkadot bridge-relayers pallet instance that is deployed at bridged
+/// chains.
+// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+pub const WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME: &str = "BridgeRelayers";
+
+decl_bridge_finality_runtime_apis!(bridge_hub_polkadot);
+decl_bridge_messages_runtime_apis!(bridge_hub_polkadot);
diff --git a/bridges/primitives/chain-kusama/src/lib.rs b/bridges/primitives/chain-kusama/src/lib.rs
index 9ada688bf11b5..8e5aec8afda33 100644
--- a/bridges/primitives/chain-kusama/src/lib.rs
+++ b/bridges/primitives/chain-kusama/src/lib.rs
@@ -56,6 +56,9 @@ impl ChainWithGrandpa for Kusama {
 	const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
 }
 
+/// Name of the parachains pallet in the Kusama runtime.
+pub const PARAS_PALLET_NAME: &str = "Paras";
+
 /// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains.
 pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa";
 
diff --git a/bridges/primitives/chain-polkadot/src/lib.rs b/bridges/primitives/chain-polkadot/src/lib.rs
index e1600102fcd46..92995601698d0 100644
--- a/bridges/primitives/chain-polkadot/src/lib.rs
+++ b/bridges/primitives/chain-polkadot/src/lib.rs
@@ -56,6 +56,9 @@ impl ChainWithGrandpa for Polkadot {
 	const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
 }
 
+/// Name of the parachains pallet in the Polkadot runtime.
+pub const PARAS_PALLET_NAME: &str = "Paras";
+
 /// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains.
 pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa";
 
diff --git a/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs
index ece925d795273..1d2373de6d350 100644
--- a/bridges/primitives/runtime/src/lib.rs
+++ b/bridges/primitives/runtime/src/lib.rs
@@ -25,8 +25,7 @@ use frame_support::{
 };
 use frame_system::RawOrigin;
 use scale_info::TypeInfo;
-use sp_core::{hash::H256, storage::StorageKey};
-use sp_io::hashing::blake2_256;
+use sp_core::storage::StorageKey;
 use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto};
 use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec};
 
@@ -59,47 +58,44 @@ pub use sp_runtime::paste;
 /// Use this when something must be shared among all instances.
 pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0];
 
-/// Bridge-with-Rialto instance id.
+/// Rialto chain id.
 pub const RIALTO_CHAIN_ID: ChainId = *b"rlto";
 
-/// Bridge-with-RialtoParachain instance id.
+/// RialtoParachain chain id.
 pub const RIALTO_PARACHAIN_CHAIN_ID: ChainId = *b"rlpa";
 
-/// Bridge-with-Millau instance id.
+/// Millau chain id.
 pub const MILLAU_CHAIN_ID: ChainId = *b"mlau";
 
-/// Bridge-with-Polkadot instance id.
+/// Polkadot chain id.
 pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot";
 
-/// Bridge-with-Kusama instance id.
+/// Kusama chain id.
 pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma";
 
-/// Bridge-with-Westend instance id.
+/// Westend chain id.
 pub const WESTEND_CHAIN_ID: ChainId = *b"wend";
 
-/// Bridge-with-Westend instance id.
+/// Westend chain id.
 pub const WESTMINT_CHAIN_ID: ChainId = *b"wmnt";
 
-/// Bridge-with-Rococo instance id.
+/// Rococo chain id.
 pub const ROCOCO_CHAIN_ID: ChainId = *b"roco";
 
-/// Bridge-with-Wococo instance id.
+/// Wococo chain id.
 pub const WOCOCO_CHAIN_ID: ChainId = *b"woco";
 
-/// Bridge-with-BridgeHubRococo instance id.
+/// BridgeHubRococo chain id.
 pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro";
 
-/// Bridge-with-BridgeHubWococo instance id.
+/// BridgeHubWococo chain id.
 pub const BRIDGE_HUB_WOCOCO_CHAIN_ID: ChainId = *b"bhwo";
 
-/// Call-dispatch module prefix.
-pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch";
+/// BridgeHubKusama chain id.
+pub const BRIDGE_HUB_KUSAMA_CHAIN_ID: ChainId = *b"bhks";
 
-/// A unique prefix for entropy when generating cross-chain account IDs.
-pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/account";
-
-/// A unique prefix for entropy when generating a cross-chain account ID for the Root account.
-pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/root";
+/// BridgeHubPolkadot chain id.
+pub const BRIDGE_HUB_POLKADOT_CHAIN_ID: ChainId = *b"bhwo";
 
 /// Generic header Id.
 #[derive(
@@ -164,41 +160,6 @@ impl<Header: HeaderT> HeaderIdProvider<Header> for Header {
 /// used for that.
 pub type ChainId = [u8; 4];
 
-/// Type of accounts on the source chain.
-pub enum SourceAccount<T> {
-	/// An account that belongs to Root (privileged origin).
-	Root,
-	/// A non-privileged account.
-	///
-	/// The embedded account ID may or may not have a private key depending on the "owner" of the
-	/// account (private key, pallet, proxy, etc.).
-	Account(T),
-}
-
-/// Derive an account ID from a foreign account ID.
-///
-/// This function returns an encoded Blake2 hash. It is the responsibility of the caller to ensure
-/// this can be successfully decoded into an AccountId.
-///
-/// The `bridge_id` is used to provide extra entropy when producing account IDs. This helps prevent
-/// AccountId collisions between different bridges on a single target chain.
-///
-/// Note: If the same `bridge_id` is used across different chains (for example, if one source chain
-/// is bridged to multiple target chains), then all the derived accounts would be the same across
-/// the different chains. This could negatively impact users' privacy across chains.
-pub fn derive_account_id<AccountId>(bridge_id: ChainId, id: SourceAccount<AccountId>) -> H256
-where
-	AccountId: Encode,
-{
-	match id {
-		SourceAccount::Root =>
-			(ROOT_ACCOUNT_DERIVATION_PREFIX, bridge_id).using_encoded(blake2_256),
-		SourceAccount::Account(id) =>
-			(ACCOUNT_DERIVATION_PREFIX, bridge_id, id).using_encoded(blake2_256),
-	}
-	.into()
-}
-
 /// Anything that has size.
 pub trait Size {
 	/// Return size of this object (in bytes).
diff --git a/bridges/relays/bin-substrate/Cargo.toml b/bridges/relays/bin-substrate/Cargo.toml
index b7453c7aef002..6984cfed00c77 100644
--- a/bridges/relays/bin-substrate/Cargo.toml
+++ b/bridges/relays/bin-substrate/Cargo.toml
@@ -37,8 +37,12 @@ parachains-relay = { path = "../parachains" }
 relay-millau-client = { path = "../client-millau" }
 relay-rialto-client = { path = "../client-rialto" }
 relay-rialto-parachain-client = { path = "../client-rialto-parachain" }
+relay-bridge-hub-kusama-client = { path = "../client-bridge-hub-kusama" }
+relay-bridge-hub-polkadot-client = { path = "../client-bridge-hub-polkadot" }
 relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" }
 relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" }
+relay-kusama-client = { path = "../client-kusama" }
+relay-polkadot-client = { path = "../client-polkadot" }
 relay-rococo-client = { path = "../client-rococo" }
 relay-substrate-client = { path = "../client-substrate" }
 relay-utils = { path = "../utils" }
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs
new file mode 100644
index 0000000000000..9abec22b98109
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs
@@ -0,0 +1,65 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! BridgeHubKusama-to-BridgeHubPolkadot messages sync entrypoint.
+
+use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge};
+use relay_bridge_hub_kusama_client::BridgeHubKusama;
+use relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder};
+
+/// BridgeHubKusama-to-BridgeHubPolkadot messages bridge.
+pub struct BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {}
+
+impl CliBridgeBase for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {
+	type Source = BridgeHubKusama;
+	type Target = BridgeHubPolkadot;
+}
+
+impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {
+	type MessagesLane = BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane;
+}
+
+substrate_relay_helper::generate_receive_message_proof_call_builder!(
+	BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane,
+	BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder,
+	relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaMessages,
+	relay_bridge_hub_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof
+);
+
+substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!(
+	BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane,
+	BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder,
+	relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotMessages,
+	relay_bridge_hub_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof
+);
+
+/// BridgeHubKusama-to-BridgeHubPolkadot messages lane.
+#[derive(Clone, Debug)]
+pub struct BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane;
+
+impl SubstrateMessageLane for BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane {
+	type SourceChain = BridgeHubKusama;
+	type TargetChain = BridgeHubPolkadot;
+
+	type ReceiveMessagesProofCallBuilder =
+		BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder;
+	type ReceiveMessagesDeliveryProofCallBuilder =
+		BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder;
+
+	type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder<BridgeHubKusama>;
+	type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder<BridgeHubPolkadot>;
+}
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs
new file mode 100644
index 0000000000000..191a84b27c270
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs
@@ -0,0 +1,65 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! BridgeHubPolkadot-to-BridgeHubKusama messages sync entrypoint.
+
+use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge};
+use relay_bridge_hub_kusama_client::BridgeHubKusama;
+use relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder};
+
+/// BridgeHubPolkadot-to-BridgeHubKusama messages bridge.
+pub struct BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {}
+
+impl CliBridgeBase for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {
+	type Source = BridgeHubPolkadot;
+	type Target = BridgeHubKusama;
+}
+
+impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {
+	type MessagesLane = BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane;
+}
+
+substrate_relay_helper::generate_receive_message_proof_call_builder!(
+	BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane,
+	BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder,
+	relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotMessages,
+	relay_bridge_hub_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof
+);
+
+substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!(
+	BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane,
+	BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder,
+	relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaMessages,
+	relay_bridge_hub_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof
+);
+
+/// BridgeHubPolkadot-to-BridgeHubKusama messages lane.
+#[derive(Clone, Debug)]
+pub struct BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane;
+
+impl SubstrateMessageLane for BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane {
+	type SourceChain = BridgeHubPolkadot;
+	type TargetChain = BridgeHubKusama;
+
+	type ReceiveMessagesProofCallBuilder =
+		BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder;
+	type ReceiveMessagesDeliveryProofCallBuilder =
+		BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder;
+
+	type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder<BridgeHubPolkadot>;
+	type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder<BridgeHubKusama>;
+}
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs
new file mode 100644
index 0000000000000..1cfaf922692f6
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs
@@ -0,0 +1,72 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Kusama-to-BridgeHubPolkadot headers sync entrypoint.
+
+use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge};
+
+use async_trait::async_trait;
+use relay_substrate_client::{AccountKeyPairOf, Client};
+use substrate_relay_helper::{
+	finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline},
+	TransactionParams,
+};
+
+/// Description of Kusama -> PolkadotBridgeHub finalized headers bridge.
+#[derive(Clone, Debug)]
+pub struct KusamaFinalityToBridgeHubPolkadot;
+
+substrate_relay_helper::generate_submit_finality_proof_call_builder!(
+	KusamaFinalityToBridgeHubPolkadot,
+	KusamaFinalityToBridgeHubPolkadotCallBuilder,
+	relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaGrandpa,
+	relay_bridge_hub_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof
+);
+
+#[async_trait]
+impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot {
+	type SourceChain = relay_kusama_client::Kusama;
+	type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+
+	type FinalityEngine = GrandpaFinalityEngine<Self::SourceChain>;
+	type SubmitFinalityProofCallBuilder = KusamaFinalityToBridgeHubPolkadotCallBuilder;
+
+	async fn start_relay_guards(
+		target_client: &Client<Self::TargetChain>,
+		_transaction_params: &TransactionParams<AccountKeyPairOf<Self::TargetChain>>,
+		enable_version_guard: bool,
+	) -> relay_substrate_client::Result<()> {
+		if enable_version_guard {
+			relay_substrate_client::guard::abort_on_spec_version_change(
+				target_client.clone(),
+				target_client.simple_runtime_version().await?.spec_version,
+			);
+		}
+		Ok(())
+	}
+}
+
+/// `Kusama` to BridgeHub `Polkadot` bridge definition.
+pub struct KusamaToBridgeHubPolkadotCliBridge {}
+
+impl CliBridgeBase for KusamaToBridgeHubPolkadotCliBridge {
+	type Source = relay_kusama_client::Kusama;
+	type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+}
+
+impl RelayToRelayHeadersCliBridge for KusamaToBridgeHubPolkadotCliBridge {
+	type Finality = KusamaFinalityToBridgeHubPolkadot;
+}
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs
new file mode 100644
index 0000000000000..e5936640cb3b8
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs
@@ -0,0 +1,75 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Kusama-to-BridgeHubPolkadot parachains sync entrypoint.
+
+use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge};
+use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
+use relay_substrate_client::{CallOf, HeaderIdOf};
+use substrate_relay_helper::parachains::{
+	SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline,
+};
+
+/// Kusama-to-BridgeHubPolkadot parachain sync description.
+#[derive(Clone, Debug)]
+pub struct BridgeHubKusamaToBridgeHubPolkadot;
+
+impl SubstrateParachainsPipeline for BridgeHubKusamaToBridgeHubPolkadot {
+	type SourceParachain = relay_bridge_hub_kusama_client::BridgeHubKusama;
+	type SourceRelayChain = relay_kusama_client::Kusama;
+	type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+
+	type SubmitParachainHeadsCallBuilder = BridgeHubKusamaToBridgeHubPolkadotCallBuilder;
+}
+
+pub struct BridgeHubKusamaToBridgeHubPolkadotCallBuilder;
+impl SubmitParachainHeadsCallBuilder<BridgeHubKusamaToBridgeHubPolkadot>
+	for BridgeHubKusamaToBridgeHubPolkadotCallBuilder
+{
+	fn build_submit_parachain_heads_call(
+		at_relay_block: HeaderIdOf<relay_kusama_client::Kusama>,
+		parachains: Vec<(ParaId, ParaHash)>,
+		parachain_heads_proof: ParaHeadsProof,
+	) -> CallOf<relay_bridge_hub_polkadot_client::BridgeHubPolkadot> {
+		relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaParachain(
+			relay_bridge_hub_polkadot_client::runtime::BridgeParachainCall::submit_parachain_heads {
+				at_relay_block: (at_relay_block.0, at_relay_block.1),
+				parachains,
+				parachain_heads_proof,
+			},
+		)
+	}
+}
+
+/// Kusama-to-BridgeHubPolkadot parachain sync description for the CLI.
+pub struct BridgeHubKusamaToBridgeHubPolkadotCliBridge {}
+
+impl ParachainToRelayHeadersCliBridge for BridgeHubKusamaToBridgeHubPolkadotCliBridge {
+	type SourceRelay = relay_kusama_client::Kusama;
+	type ParachainFinality = BridgeHubKusamaToBridgeHubPolkadot;
+	type RelayFinality =
+		crate::bridges::kusama_polkadot::kusama_headers_to_bridge_hub_polkadot::KusamaFinalityToBridgeHubPolkadot;
+}
+
+impl CliBridgeBase for BridgeHubKusamaToBridgeHubPolkadotCliBridge {
+	type Source = relay_bridge_hub_kusama_client::BridgeHubKusama;
+	type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+}
+
+impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotCliBridge {
+	type MessagesLane =
+	crate::bridges::kusama_polkadot::bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane;
+}
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs
new file mode 100644
index 0000000000000..65cd8d9ded6cd
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs
@@ -0,0 +1,24 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of all bridges between Kusama Bridge Hub and Polkadot Bridge Hub.
+
+pub mod bridge_hub_kusama_messages_to_bridge_hub_polkadot;
+pub mod bridge_hub_polkadot_messages_to_bridge_hub_kusama;
+pub mod kusama_headers_to_bridge_hub_polkadot;
+pub mod kusama_parachains_to_bridge_hub_polkadot;
+pub mod polkadot_headers_to_bridge_hub_kusama;
+pub mod polkadot_parachains_to_bridge_hub_kusama;
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs
new file mode 100644
index 0000000000000..6827c24768cb8
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs
@@ -0,0 +1,72 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Polkadot-to-KusamaBridgeHub headers sync entrypoint.
+
+use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge};
+
+use async_trait::async_trait;
+use relay_substrate_client::{AccountKeyPairOf, Client};
+use substrate_relay_helper::{
+	finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline},
+	TransactionParams,
+};
+
+/// Description of Polkadot -> KusamaBridgeHub finalized headers bridge.
+#[derive(Clone, Debug)]
+pub struct PolkadotFinalityToBridgeHubKusama;
+
+substrate_relay_helper::generate_submit_finality_proof_call_builder!(
+	PolkadotFinalityToBridgeHubKusama,
+	PolkadotFinalityToBridgeHubKusamaCallBuilder,
+	relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotGrandpa,
+	relay_bridge_hub_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof
+);
+
+#[async_trait]
+impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama {
+	type SourceChain = relay_polkadot_client::Polkadot;
+	type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama;
+
+	type FinalityEngine = GrandpaFinalityEngine<Self::SourceChain>;
+	type SubmitFinalityProofCallBuilder = PolkadotFinalityToBridgeHubKusamaCallBuilder;
+
+	async fn start_relay_guards(
+		target_client: &Client<Self::TargetChain>,
+		_transaction_params: &TransactionParams<AccountKeyPairOf<Self::TargetChain>>,
+		enable_version_guard: bool,
+	) -> relay_substrate_client::Result<()> {
+		if enable_version_guard {
+			relay_substrate_client::guard::abort_on_spec_version_change(
+				target_client.clone(),
+				target_client.simple_runtime_version().await?.spec_version,
+			);
+		}
+		Ok(())
+	}
+}
+
+/// `Polkadot` to BridgeHub `Kusama` bridge definition.
+pub struct PolkadotToBridgeHubKusamaCliBridge {}
+
+impl CliBridgeBase for PolkadotToBridgeHubKusamaCliBridge {
+	type Source = relay_polkadot_client::Polkadot;
+	type Target = relay_bridge_hub_kusama_client::BridgeHubKusama;
+}
+
+impl RelayToRelayHeadersCliBridge for PolkadotToBridgeHubKusamaCliBridge {
+	type Finality = PolkadotFinalityToBridgeHubKusama;
+}
diff --git a/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs
new file mode 100644
index 0000000000000..f2a7f7309cf1d
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs
@@ -0,0 +1,75 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Polkadot-to-BridgeHubKusama parachains sync entrypoint.
+
+use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge};
+use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
+use relay_substrate_client::{CallOf, HeaderIdOf};
+use substrate_relay_helper::parachains::{
+	SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline,
+};
+
+/// Polkadot-to-BridgeHubKusama parachain sync description.
+#[derive(Clone, Debug)]
+pub struct BridgeHubPolkadotToBridgeHubKusama;
+
+impl SubstrateParachainsPipeline for BridgeHubPolkadotToBridgeHubKusama {
+	type SourceParachain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+	type SourceRelayChain = relay_polkadot_client::Polkadot;
+	type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama;
+
+	type SubmitParachainHeadsCallBuilder = BridgeHubPolkadotToBridgeHubKusamaCallBuilder;
+}
+
+pub struct BridgeHubPolkadotToBridgeHubKusamaCallBuilder;
+impl SubmitParachainHeadsCallBuilder<BridgeHubPolkadotToBridgeHubKusama>
+	for BridgeHubPolkadotToBridgeHubKusamaCallBuilder
+{
+	fn build_submit_parachain_heads_call(
+		at_relay_block: HeaderIdOf<relay_polkadot_client::Polkadot>,
+		parachains: Vec<(ParaId, ParaHash)>,
+		parachain_heads_proof: ParaHeadsProof,
+	) -> CallOf<relay_bridge_hub_kusama_client::BridgeHubKusama> {
+		relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotParachain(
+			bp_parachains::BridgeParachainCall::submit_parachain_heads {
+				at_relay_block: (at_relay_block.0, at_relay_block.1),
+				parachains,
+				parachain_heads_proof,
+			},
+		)
+	}
+}
+
+/// Polkadot-to-BridgeHubKusama parachain sync description for the CLI.
+pub struct BridgeHubPolkadotToBridgeHubKusamaCliBridge {}
+
+impl ParachainToRelayHeadersCliBridge for BridgeHubPolkadotToBridgeHubKusamaCliBridge {
+	type SourceRelay = relay_polkadot_client::Polkadot;
+	type ParachainFinality = BridgeHubPolkadotToBridgeHubKusama;
+	type RelayFinality =
+		crate::bridges::kusama_polkadot::polkadot_headers_to_bridge_hub_kusama::PolkadotFinalityToBridgeHubKusama;
+}
+
+impl CliBridgeBase for BridgeHubPolkadotToBridgeHubKusamaCliBridge {
+	type Source = relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+	type Target = relay_bridge_hub_kusama_client::BridgeHubKusama;
+}
+
+impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaCliBridge {
+	type MessagesLane =
+	crate::bridges::kusama_polkadot::bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane;
+}
diff --git a/bridges/relays/bin-substrate/src/bridges/mod.rs b/bridges/relays/bin-substrate/src/bridges/mod.rs
new file mode 100644
index 0000000000000..62e69cc0e5fbd
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/mod.rs
@@ -0,0 +1,23 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of all bridges that the relay is able to serve.
+
+pub mod kusama_polkadot;
+pub mod rialto_millau;
+pub mod rialto_parachain_millau;
+pub mod rococo_wococo;
+pub mod westend_millau;
diff --git a/bridges/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/bridges/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs
similarity index 94%
rename from bridges/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs
index e136b800b17a8..f805b29c6a943 100644
--- a/bridges/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs
+++ b/bridges/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs
@@ -51,5 +51,6 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge {
 }
 
 impl MessagesCliBridge for MillauToRialtoCliBridge {
-	type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto;
+	type MessagesLane =
+		crate::bridges::rialto_millau::millau_messages_to_rialto::MillauMessagesToRialto;
 }
diff --git a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/bridges/relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs
diff --git a/bridges/relays/bin-substrate/src/bridges/rialto_millau/mod.rs b/bridges/relays/bin-substrate/src/bridges/rialto_millau/mod.rs
new file mode 100644
index 0000000000000..2353b58ce616e
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/rialto_millau/mod.rs
@@ -0,0 +1,22 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of all bridges between Rialto and Millau.
+
+pub mod millau_headers_to_rialto;
+pub mod millau_messages_to_rialto;
+pub mod rialto_headers_to_millau;
+pub mod rialto_messages_to_millau;
diff --git a/bridges/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/bridges/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs
similarity index 94%
rename from bridges/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs
index 208b2638af01e..7c979f5279567 100644
--- a/bridges/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs
+++ b/bridges/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs
@@ -51,5 +51,6 @@ impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge {
 }
 
 impl MessagesCliBridge for RialtoToMillauCliBridge {
-	type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau;
+	type MessagesLane =
+		crate::bridges::rialto_millau::rialto_messages_to_millau::RialtoMessagesToMillau;
 }
diff --git a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/bridges/relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs
diff --git a/bridges/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs
similarity index 96%
rename from bridges/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs
index 4a99d73147b29..d1c090c0797e0 100644
--- a/bridges/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs
+++ b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs
@@ -72,5 +72,5 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge {
 
 impl MessagesCliBridge for MillauToRialtoParachainCliBridge {
 	type MessagesLane =
-		crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain;
+		crate::bridges::rialto_parachain_millau::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain;
 }
diff --git a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs
diff --git a/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs
new file mode 100644
index 0000000000000..f0613d1511eb3
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs
@@ -0,0 +1,22 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of all bridges between Rialto Parachain and Millau.
+
+pub mod millau_headers_to_rialto_parachain;
+pub mod millau_messages_to_rialto_parachain;
+pub mod rialto_parachain_messages_to_millau;
+pub mod rialto_parachains_to_millau;
diff --git a/bridges/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs
diff --git a/bridges/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs
similarity index 91%
rename from bridges/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs
rename to bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs
index 37eb848fe5f8e..04f2b5aa7c745 100644
--- a/bridges/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs
+++ b/bridges/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs
@@ -55,10 +55,11 @@ impl CliBridgeBase for RialtoParachainToMillauCliBridge {
 impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge {
 	type SourceRelay = Rialto;
 	type ParachainFinality = RialtoParachainsToMillau;
-	type RelayFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau;
+	type RelayFinality =
+		crate::bridges::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau;
 }
 
 impl MessagesCliBridge for RialtoParachainToMillauCliBridge {
 	type MessagesLane =
-		crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau;
+	crate::bridges::rialto_parachain_millau::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau;
 }
diff --git a/bridges/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs
rename to bridges/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs
diff --git a/bridges/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs
rename to bridges/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs
diff --git a/bridges/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs
new file mode 100644
index 0000000000000..64330a92252cd
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs
@@ -0,0 +1,24 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of all bridges between Rococo Bridge Hub and Wococo Bridge Hub.
+
+pub mod bridge_hub_rococo_messages_to_bridge_hub_wococo;
+pub mod bridge_hub_wococo_messages_to_bridge_hub_rococo;
+pub mod rococo_headers_to_bridge_hub_wococo;
+pub mod rococo_parachains_to_bridge_hub_wococo;
+pub mod wococo_headers_to_bridge_hub_rococo;
+pub mod wococo_parachains_to_bridge_hub_rococo;
diff --git a/bridges/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs
rename to bridges/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs
diff --git a/bridges/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs
similarity index 92%
rename from bridges/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs
rename to bridges/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs
index ba0c10beae424..78b4ff35a7d45 100644
--- a/bridges/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs
+++ b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs
@@ -61,7 +61,7 @@ impl ParachainToRelayHeadersCliBridge for BridgeHubRococoToBridgeHubWococoCliBri
 	type SourceRelay = relay_rococo_client::Rococo;
 	type ParachainFinality = BridgeHubRococoToBridgeHubWococo;
 	type RelayFinality =
-		crate::chains::rococo_headers_to_bridge_hub_wococo::RococoFinalityToBridgeHubWococo;
+		crate::bridges::rococo_wococo::rococo_headers_to_bridge_hub_wococo::RococoFinalityToBridgeHubWococo;
 }
 
 impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge {
@@ -71,5 +71,5 @@ impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge {
 
 impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge {
 	type MessagesLane =
-	crate::chains::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane;
+	crate::bridges::rococo_wococo::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane;
 }
diff --git a/bridges/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs
rename to bridges/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs
diff --git a/bridges/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs
similarity index 92%
rename from bridges/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs
rename to bridges/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs
index 028d8c9e17dba..bc76e377c9214 100644
--- a/bridges/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs
+++ b/bridges/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs
@@ -61,7 +61,7 @@ impl ParachainToRelayHeadersCliBridge for BridgeHubWococoToBridgeHubRococoCliBri
 	type SourceRelay = relay_wococo_client::Wococo;
 	type ParachainFinality = BridgeHubWococoToBridgeHubRococo;
 	type RelayFinality =
-		crate::chains::wococo_headers_to_bridge_hub_rococo::WococoFinalityToBridgeHubRococo;
+		crate::bridges::rococo_wococo::wococo_headers_to_bridge_hub_rococo::WococoFinalityToBridgeHubRococo;
 }
 
 impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge {
@@ -71,5 +71,5 @@ impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge {
 
 impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge {
 	type MessagesLane =
-	crate::chains::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane;
+	crate::bridges::rococo_wococo::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane;
 }
diff --git a/bridges/relays/bin-substrate/src/bridges/westend_millau/mod.rs b/bridges/relays/bin-substrate/src/bridges/westend_millau/mod.rs
new file mode 100644
index 0000000000000..10bc19241ce12
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/bridges/westend_millau/mod.rs
@@ -0,0 +1,20 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of all bridges between Westend and Millau.
+
+pub mod westend_headers_to_millau;
+pub mod westend_parachains_to_millau;
diff --git a/bridges/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/bridges/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs
similarity index 100%
rename from bridges/relays/bin-substrate/src/chains/westend_headers_to_millau.rs
rename to bridges/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs
diff --git a/bridges/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/bridges/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs
similarity index 95%
rename from bridges/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs
rename to bridges/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs
index abd9e6137bb32..0556ecab368eb 100644
--- a/bridges/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs
+++ b/bridges/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs
@@ -49,7 +49,8 @@ pub struct WestmintToMillauCliBridge {}
 impl ParachainToRelayHeadersCliBridge for WestmintToMillauCliBridge {
 	type SourceRelay = Westend;
 	type ParachainFinality = WestendParachainsToMillau;
-	type RelayFinality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau;
+	type RelayFinality =
+		crate::bridges::westend_millau::westend_headers_to_millau::WestendFinalityToMillau;
 }
 
 impl CliBridgeBase for WestmintToMillauCliBridge {
diff --git a/bridges/relays/bin-substrate/src/chains/kusama.rs b/bridges/relays/bin-substrate/src/chains/kusama.rs
new file mode 100644
index 0000000000000..6d5a4764f91ec
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/chains/kusama.rs
@@ -0,0 +1,32 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Kusama + Kusama parachains specification for CLI.
+
+use crate::cli::CliChain;
+use relay_bridge_hub_kusama_client::BridgeHubKusama;
+use relay_kusama_client::Kusama;
+use relay_substrate_client::SimpleRuntimeVersion;
+
+impl CliChain for Kusama {
+	const RUNTIME_VERSION: Option<SimpleRuntimeVersion> = None;
+}
+
+impl CliChain for BridgeHubKusama {
+	// TODO: fix me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	const RUNTIME_VERSION: Option<SimpleRuntimeVersion> =
+		Some(SimpleRuntimeVersion { spec_version: 4242, transaction_version: 42 });
+}
diff --git a/bridges/relays/bin-substrate/src/chains/mod.rs b/bridges/relays/bin-substrate/src/chains/mod.rs
index 7aad5f44e8908..b1a91ed1e85cb 100644
--- a/bridges/relays/bin-substrate/src/chains/mod.rs
+++ b/bridges/relays/bin-substrate/src/chains/mod.rs
@@ -16,24 +16,9 @@
 
 //! Chain-specific relayer configuration.
 
-pub mod bridge_hub_rococo_messages_to_bridge_hub_wococo;
-pub mod bridge_hub_wococo_messages_to_bridge_hub_rococo;
-pub mod millau_headers_to_rialto;
-pub mod millau_headers_to_rialto_parachain;
-pub mod millau_messages_to_rialto;
-pub mod millau_messages_to_rialto_parachain;
-pub mod rialto_headers_to_millau;
-pub mod rialto_messages_to_millau;
-pub mod rialto_parachain_messages_to_millau;
-pub mod rialto_parachains_to_millau;
-pub mod rococo_headers_to_bridge_hub_wococo;
-pub mod rococo_parachains_to_bridge_hub_wococo;
-pub mod westend_headers_to_millau;
-pub mod westend_parachains_to_millau;
-pub mod wococo_headers_to_bridge_hub_rococo;
-pub mod wococo_parachains_to_bridge_hub_rococo;
-
+mod kusama;
 mod millau;
+mod polkadot;
 mod rialto;
 mod rialto_parachain;
 mod rococo;
diff --git a/bridges/relays/bin-substrate/src/chains/polkadot.rs b/bridges/relays/bin-substrate/src/chains/polkadot.rs
new file mode 100644
index 0000000000000..4fe5a48398bcd
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/chains/polkadot.rs
@@ -0,0 +1,32 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Polkadot + Polkadot parachains specification for CLI.
+
+use crate::cli::CliChain;
+use relay_bridge_hub_polkadot_client::BridgeHubPolkadot;
+use relay_polkadot_client::Polkadot;
+use relay_substrate_client::SimpleRuntimeVersion;
+
+impl CliChain for Polkadot {
+	const RUNTIME_VERSION: Option<SimpleRuntimeVersion> = None;
+}
+
+impl CliChain for BridgeHubPolkadot {
+	// TODO: fix me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	const RUNTIME_VERSION: Option<SimpleRuntimeVersion> =
+		Some(SimpleRuntimeVersion { spec_version: 4242, transaction_version: 42 });
+}
diff --git a/bridges/relays/bin-substrate/src/cli/bridge.rs b/bridges/relays/bin-substrate/src/cli/bridge.rs
index 208f67c527be6..a3cacec331394 100644
--- a/bridges/relays/bin-substrate/src/cli/bridge.rs
+++ b/bridges/relays/bin-substrate/src/cli/bridge.rs
@@ -33,6 +33,8 @@ pub enum FullBridge {
 	RialtoParachainToMillau,
 	BridgeHubRococoToBridgeHubWococo,
 	BridgeHubWococoToBridgeHubRococo,
+	BridgeHubKusamaToBridgeHubPolkadot,
+	BridgeHubPolkadotToBridgeHubKusama,
 }
 
 impl FullBridge {
@@ -43,7 +45,10 @@ impl FullBridge {
 			Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX,
 			Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX,
 			Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX,
-			Self::BridgeHubRococoToBridgeHubWococo | Self::BridgeHubWococoToBridgeHubRococo =>
+			Self::BridgeHubRococoToBridgeHubWococo |
+			Self::BridgeHubWococoToBridgeHubRococo |
+			Self::BridgeHubKusamaToBridgeHubPolkadot |
+			Self::BridgeHubPolkadotToBridgeHubKusama =>
 				unimplemented!("Relay doesn't support send-message subcommand on bridge hubs"),
 		}
 	}
diff --git a/bridges/relays/bin-substrate/src/cli/init_bridge.rs b/bridges/relays/bin-substrate/src/cli/init_bridge.rs
index d6df1eaeeaa14..95cd02f6c6fcc 100644
--- a/bridges/relays/bin-substrate/src/cli/init_bridge.rs
+++ b/bridges/relays/bin-substrate/src/cli/init_bridge.rs
@@ -18,13 +18,17 @@ use async_trait::async_trait;
 use codec::Encode;
 
 use crate::{
-	chains::{
-		millau_headers_to_rialto::MillauToRialtoCliBridge,
-		millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
-		rialto_headers_to_millau::RialtoToMillauCliBridge,
-		rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge,
-		westend_headers_to_millau::WestendToMillauCliBridge,
-		wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge,
+	bridges::{
+		rialto_millau::{
+			millau_headers_to_rialto::MillauToRialtoCliBridge,
+			rialto_headers_to_millau::RialtoToMillauCliBridge,
+		},
+		rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
+		rococo_wococo::{
+			rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge,
+			wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge,
+		},
+		westend_millau::westend_headers_to_millau::WestendToMillauCliBridge,
 	},
 	cli::{bridge::CliBridgeBase, chain_schema::*},
 };
diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers.rs b/bridges/relays/bin-substrate/src/cli/relay_headers.rs
index 239ab8d62fdd0..fbe360d3cd780 100644
--- a/bridges/relays/bin-substrate/src/cli/relay_headers.rs
+++ b/bridges/relays/bin-substrate/src/cli/relay_headers.rs
@@ -20,13 +20,21 @@ use sp_core::Pair;
 use structopt::StructOpt;
 use strum::{EnumString, EnumVariantNames, VariantNames};
 
-use crate::chains::{
-	millau_headers_to_rialto::MillauToRialtoCliBridge,
-	millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
-	rialto_headers_to_millau::RialtoToMillauCliBridge,
-	rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge,
-	westend_headers_to_millau::WestendToMillauCliBridge,
-	wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge,
+use crate::bridges::{
+	kusama_polkadot::{
+		kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge,
+		polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge,
+	},
+	rialto_millau::{
+		millau_headers_to_rialto::MillauToRialtoCliBridge,
+		rialto_headers_to_millau::RialtoToMillauCliBridge,
+	},
+	rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
+	rococo_wococo::{
+		rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge,
+		wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge,
+	},
+	westend_millau::westend_headers_to_millau::WestendToMillauCliBridge,
 };
 use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
 use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline;
@@ -63,6 +71,8 @@ pub enum RelayHeadersBridge {
 	MillauToRialtoParachain,
 	RococoToBridgeHubWococo,
 	WococoToBridgeHubRococo,
+	KusamaToBridgeHubPolkadot,
+	PolkadotToBridgeHubKusama,
 }
 
 #[async_trait]
@@ -109,6 +119,8 @@ impl HeadersRelayer for WestendToMillauCliBridge {}
 impl HeadersRelayer for MillauToRialtoParachainCliBridge {}
 impl HeadersRelayer for RococoToBridgeHubWococoCliBridge {}
 impl HeadersRelayer for WococoToBridgeHubRococoCliBridge {}
+impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {}
+impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {}
 
 impl RelayHeaders {
 	/// Run the command.
@@ -123,6 +135,10 @@ impl RelayHeaders {
 				RococoToBridgeHubWococoCliBridge::relay_headers(self),
 			RelayHeadersBridge::WococoToBridgeHubRococo =>
 				WococoToBridgeHubRococoCliBridge::relay_headers(self),
+			RelayHeadersBridge::KusamaToBridgeHubPolkadot =>
+				KusamaToBridgeHubPolkadotCliBridge::relay_headers(self),
+			RelayHeadersBridge::PolkadotToBridgeHubKusama =>
+				PolkadotToBridgeHubKusamaCliBridge::relay_headers(self),
 		}
 		.await
 	}
diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs
index 193632c28b427..5384c8ff9e9fd 100644
--- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs
+++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs
@@ -39,13 +39,19 @@ use relay_to_parachain::*;
 use relay_to_relay::*;
 
 use crate::{
-	chains::{
-		millau_headers_to_rialto::MillauToRialtoCliBridge,
-		millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
-		rialto_headers_to_millau::RialtoToMillauCliBridge,
-		rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
-		rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge,
-		wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge,
+	bridges::{
+		rialto_millau::{
+			millau_headers_to_rialto::MillauToRialtoCliBridge,
+			rialto_headers_to_millau::RialtoToMillauCliBridge,
+		},
+		rialto_parachain_millau::{
+			millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
+			rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
+		},
+		rococo_wococo::{
+			rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge,
+			wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge,
+		},
 	},
 	cli::{
 		bridge::{
diff --git a/bridges/relays/bin-substrate/src/cli/relay_messages.rs b/bridges/relays/bin-substrate/src/cli/relay_messages.rs
index e0250ef1e472b..1624524e4a5b1 100644
--- a/bridges/relays/bin-substrate/src/cli/relay_messages.rs
+++ b/bridges/relays/bin-substrate/src/cli/relay_messages.rs
@@ -19,13 +19,23 @@ use sp_core::Pair;
 use structopt::StructOpt;
 use strum::VariantNames;
 
-use crate::chains::{
-	bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge,
-	bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge,
-	millau_headers_to_rialto::MillauToRialtoCliBridge,
-	millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
-	rialto_headers_to_millau::RialtoToMillauCliBridge,
-	rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
+use crate::bridges::{
+	kusama_polkadot::{
+		bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge,
+		bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge,
+	},
+	rialto_millau::{
+		millau_headers_to_rialto::MillauToRialtoCliBridge,
+		rialto_headers_to_millau::RialtoToMillauCliBridge,
+	},
+	rialto_parachain_millau::{
+		millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
+		rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
+	},
+	rococo_wococo::{
+		bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge,
+		bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge,
+	},
 };
 use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions};
 use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams};
@@ -96,6 +106,8 @@ impl MessagesRelayer for MillauToRialtoParachainCliBridge {}
 impl MessagesRelayer for RialtoParachainToMillauCliBridge {}
 impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {}
 impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {}
+impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {}
+impl MessagesRelayer for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {}
 
 impl RelayMessages {
 	/// Run the command.
@@ -111,6 +123,10 @@ impl RelayMessages {
 				BridgeHubRococoToBridgeHubWococoMessagesCliBridge::relay_messages(self),
 			FullBridge::BridgeHubWococoToBridgeHubRococo =>
 				BridgeHubWococoToBridgeHubRococoMessagesCliBridge::relay_messages(self),
+			FullBridge::BridgeHubKusamaToBridgeHubPolkadot =>
+				BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self),
+			FullBridge::BridgeHubPolkadotToBridgeHubKusama =>
+				BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self),
 		}
 		.await
 	}
diff --git a/bridges/relays/bin-substrate/src/cli/relay_parachains.rs b/bridges/relays/bin-substrate/src/cli/relay_parachains.rs
index 4e59dc14733fc..8c2aa1cc8c1f6 100644
--- a/bridges/relays/bin-substrate/src/cli/relay_parachains.rs
+++ b/bridges/relays/bin-substrate/src/cli/relay_parachains.rs
@@ -14,11 +14,17 @@
 // You should have received a copy of the GNU General Public License
 // along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
 
-use crate::chains::{
-	rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
-	rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge,
-	westend_parachains_to_millau::WestmintToMillauCliBridge,
-	wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge,
+use crate::bridges::{
+	kusama_polkadot::{
+		kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge,
+		polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge,
+	},
+	rialto_parachain_millau::rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
+	rococo_wococo::{
+		rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge,
+		wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge,
+	},
+	westend_millau::westend_parachains_to_millau::WestmintToMillauCliBridge,
 };
 use async_std::sync::Mutex;
 use async_trait::async_trait;
@@ -60,10 +66,11 @@ pub struct RelayParachains {
 #[strum(serialize_all = "kebab_case")]
 pub enum RelayParachainsBridge {
 	RialtoToMillau,
-	// TODO:check-parameter - rename to WestmintToMillau?
 	WestendToMillau,
-	BridgeHubRococoToBridgeHubWococo,
-	BridgeHubWococoToBridgeHubRococo,
+	RococoToBridgeHubWococo,
+	WococoToBridgeHubRococo,
+	KusamaToBridgeHubPolkadot,
+	PolkadotToBridgeHubKusama,
 }
 
 #[async_trait]
@@ -75,7 +82,7 @@ where
 		TargetClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
 	<Self as CliBridgeBase>::Source: Parachain,
 {
-	async fn relay_headers(data: RelayParachains) -> anyhow::Result<()> {
+	async fn relay_parachains(data: RelayParachains) -> anyhow::Result<()> {
 		let source_client = data.source.into_client::<Self::SourceRelay>().await?;
 		let source_client = ParachainsSource::<Self::ParachainFinality>::new(
 			source_client,
@@ -108,25 +115,28 @@ where
 }
 
 impl ParachainsRelayer for RialtoParachainToMillauCliBridge {}
-
 impl ParachainsRelayer for WestmintToMillauCliBridge {}
-
 impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {}
-
 impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {}
+impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {}
+impl ParachainsRelayer for BridgeHubPolkadotToBridgeHubKusamaCliBridge {}
 
 impl RelayParachains {
 	/// Run the command.
 	pub async fn run(self) -> anyhow::Result<()> {
 		match self.bridge {
 			RelayParachainsBridge::RialtoToMillau =>
-				RialtoParachainToMillauCliBridge::relay_headers(self),
+				RialtoParachainToMillauCliBridge::relay_parachains(self),
 			RelayParachainsBridge::WestendToMillau =>
-				WestmintToMillauCliBridge::relay_headers(self),
-			RelayParachainsBridge::BridgeHubRococoToBridgeHubWococo =>
-				BridgeHubRococoToBridgeHubWococoCliBridge::relay_headers(self),
-			RelayParachainsBridge::BridgeHubWococoToBridgeHubRococo =>
-				BridgeHubWococoToBridgeHubRococoCliBridge::relay_headers(self),
+				WestmintToMillauCliBridge::relay_parachains(self),
+			RelayParachainsBridge::RococoToBridgeHubWococo =>
+				BridgeHubRococoToBridgeHubWococoCliBridge::relay_parachains(self),
+			RelayParachainsBridge::WococoToBridgeHubRococo =>
+				BridgeHubWococoToBridgeHubRococoCliBridge::relay_parachains(self),
+			RelayParachainsBridge::KusamaToBridgeHubPolkadot =>
+				BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self),
+			RelayParachainsBridge::PolkadotToBridgeHubKusama =>
+				BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self),
 		}
 		.await
 	}
diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs
index 9f14028c4aee4..09d7f72b7f4b5 100644
--- a/bridges/relays/bin-substrate/src/cli/send_message.rs
+++ b/bridges/relays/bin-substrate/src/cli/send_message.rs
@@ -15,11 +15,15 @@
 // along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
 
 use crate::{
-	chains::{
-		millau_headers_to_rialto::MillauToRialtoCliBridge,
-		millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
-		rialto_headers_to_millau::RialtoToMillauCliBridge,
-		rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
+	bridges::{
+		rialto_millau::{
+			millau_headers_to_rialto::MillauToRialtoCliBridge,
+			rialto_headers_to_millau::RialtoToMillauCliBridge,
+		},
+		rialto_parachain_millau::{
+			millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge,
+			rialto_parachains_to_millau::RialtoParachainToMillauCliBridge,
+		},
 	},
 	cli::{
 		bridge::{FullBridge, MessagesCliBridge},
@@ -114,6 +118,12 @@ impl SendMessage {
 			FullBridge::BridgeHubWococoToBridgeHubRococo => unimplemented!(
 				"Sending message from BridgeHubWococo to BridgeHubRococo is not supported"
 			),
+			FullBridge::BridgeHubKusamaToBridgeHubPolkadot => unimplemented!(
+				"Sending message from BridgeHubKusama to BridgeHubPolkadot is not supported"
+			),
+			FullBridge::BridgeHubPolkadotToBridgeHubKusama => unimplemented!(
+				"Sending message from BridgeHubPolkadot to BridgeHubKusama is not supported"
+			),
 		}
 		.await
 	}
diff --git a/bridges/relays/bin-substrate/src/main.rs b/bridges/relays/bin-substrate/src/main.rs
index 8bd89a4193627..33a423b076628 100644
--- a/bridges/relays/bin-substrate/src/main.rs
+++ b/bridges/relays/bin-substrate/src/main.rs
@@ -18,6 +18,7 @@
 
 #![warn(missing_docs)]
 
+mod bridges;
 mod chains;
 mod cli;
 
diff --git a/bridges/relays/client-bridge-hub-kusama/Cargo.toml b/bridges/relays/client-bridge-hub-kusama/Cargo.toml
new file mode 100644
index 0000000000000..3485323ca6c51
--- /dev/null
+++ b/bridges/relays/client-bridge-hub-kusama/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "relay-bridge-hub-kusama-client"
+version = "0.1.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2021"
+license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] }
+scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
+relay-substrate-client = { path = "../client-substrate" }
+
+# Bridge dependencies
+
+bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" }
+bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" }
+bp-header-chain = { path = "../../primitives/header-chain" }
+bp-messages = { path = "../../primitives/messages" }
+bp-parachains = { path = "../../primitives/parachains" }
+bp-runtime = { path = "../../primitives/runtime" }
+bp-polkadot = { path = "../../primitives/chain-polkadot" }
+
+bridge-runtime-common = { path = "../../bin/runtime-common" }
+
+# Substrate Dependencies
+
+sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/bridges/relays/client-bridge-hub-kusama/src/lib.rs b/bridges/relays/client-bridge-hub-kusama/src/lib.rs
new file mode 100644
index 0000000000000..6549a32ca7956
--- /dev/null
+++ b/bridges/relays/client-bridge-hub-kusama/src/lib.rs
@@ -0,0 +1,162 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Types used to connect to the BridgeHub-Kusama-Substrate parachain.
+
+use bp_bridge_hub_kusama::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL};
+use bp_messages::MessageNonce;
+use bp_runtime::ChainId;
+use codec::Encode;
+use relay_substrate_client::{
+	Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet,
+	Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider,
+	UnsignedTransaction,
+};
+use sp_core::{storage::StorageKey, Pair};
+use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
+use std::time::Duration;
+
+/// Re-export runtime wrapper
+pub mod runtime_wrapper;
+pub use runtime_wrapper as runtime;
+
+/// Kusama chain definition
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct BridgeHubKusama;
+
+impl UnderlyingChainProvider for BridgeHubKusama {
+	type Chain = bp_bridge_hub_kusama::BridgeHubKusama;
+}
+
+impl Chain for BridgeHubKusama {
+	const ID: ChainId = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID;
+	const NAME: &'static str = "BridgeHubKusama";
+	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
+		bp_bridge_hub_kusama::BEST_FINALIZED_BRIDGE_HUB_KUSAMA_HEADER_METHOD;
+	const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL;
+
+	type SignedBlock = bp_bridge_hub_kusama::SignedBlock;
+	type Call = runtime::Call;
+}
+
+impl ChainWithBalances for BridgeHubKusama {
+	fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
+		bp_bridge_hub_kusama::AccountInfoStorageMapKeyProvider::final_key(account_id)
+	}
+}
+
+impl ChainWithUtilityPallet for BridgeHubKusama {
+	type UtilityPallet = MockedRuntimeUtilityPallet<runtime::Call>;
+}
+
+impl ChainWithTransactions for BridgeHubKusama {
+	type AccountKeyPair = sp_core::sr25519::Pair;
+	type SignedTransaction = runtime::UncheckedExtrinsic;
+
+	fn sign_transaction(
+		param: SignParam<Self>,
+		unsigned: UnsignedTransaction<Self>,
+	) -> Result<Self::SignedTransaction, SubstrateError> {
+		let raw_payload = SignedPayload::new(
+			unsigned.call,
+			runtime::SignedExtension::from_params(
+				param.spec_version,
+				param.transaction_version,
+				unsigned.era,
+				param.genesis_hash,
+				unsigned.nonce,
+				unsigned.tip,
+			),
+		)?;
+
+		let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
+		let signer: sp_runtime::MultiSigner = param.signer.public().into();
+		let (call, extra, _) = raw_payload.deconstruct();
+
+		Ok(runtime::UncheckedExtrinsic::new_signed(
+			call,
+			signer.into_account().into(),
+			signature.into(),
+			extra,
+		))
+	}
+
+	fn is_signed(tx: &Self::SignedTransaction) -> bool {
+		tx.signature.is_some()
+	}
+
+	fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool {
+		tx.signature
+			.as_ref()
+			.map(|(address, _, _)| {
+				*address == bp_bridge_hub_kusama::Address::Id(signer.public().into())
+			})
+			.unwrap_or(false)
+	}
+
+	fn parse_transaction(tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self>> {
+		let extra = &tx.signature.as_ref()?.2;
+		Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip()))
+	}
+}
+
+impl ChainWithMessages for BridgeHubKusama {
+	const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
+		bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME;
+	const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> =
+		Some(bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME);
+
+	const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
+		bp_bridge_hub_kusama::TO_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD;
+	const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
+		bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD;
+
+	const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
+		bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
+	const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
+		bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use relay_substrate_client::TransactionEra;
+
+	#[test]
+	fn parse_transaction_works() {
+		let unsigned = UnsignedTransaction {
+			call: runtime::Call::System(relay_substrate_client::calls::SystemCall::remark(
+				b"Hello world!".to_vec(),
+			))
+			.into(),
+			nonce: 777,
+			tip: 888,
+			era: TransactionEra::immortal(),
+		};
+		let signed_transaction = BridgeHubKusama::sign_transaction(
+			SignParam {
+				spec_version: 42,
+				transaction_version: 50000,
+				genesis_hash: [42u8; 32].into(),
+				signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(),
+			},
+			unsigned.clone(),
+		)
+		.unwrap();
+		let parsed_transaction = BridgeHubKusama::parse_transaction(signed_transaction).unwrap();
+		assert_eq!(parsed_transaction, unsigned);
+	}
+}
diff --git a/bridges/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs b/bridges/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs
new file mode 100644
index 0000000000000..18bdafc0f04de
--- /dev/null
+++ b/bridges/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs
@@ -0,0 +1,74 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Types that are specific to the BridgeHubKusama runtime.
+// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945)
+
+use codec::{Decode, Encode};
+use scale_info::TypeInfo;
+
+pub use bp_bridge_hub_kusama::SignedExtension;
+pub use bp_header_chain::BridgeGrandpaCallOf;
+pub use bp_parachains::BridgeParachainCall;
+pub use bridge_runtime_common::messages::BridgeMessagesCallOf;
+pub use relay_substrate_client::calls::{SystemCall, UtilityCall};
+
+/// Unchecked BridgeHubKusama extrinsic.
+pub type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic<Call, SignedExtension>;
+
+// The indirect pallet call used to sync `Polkadot` GRANDPA finality to `BHKusama`.
+pub type BridgePolkadotGrandpaCall = BridgeGrandpaCallOf<bp_polkadot::Polkadot>;
+// The indirect pallet call used to sync `BridgeHubPolkadot` messages to `BHKusama`.
+pub type BridgePolkadotMessagesCall =
+	BridgeMessagesCallOf<bp_bridge_hub_polkadot::BridgeHubPolkadot>;
+
+/// `BridgeHubKusama` Runtime `Call` enum.
+///
+/// The enum represents a subset of possible `Call`s we can send to `BridgeHubKusama` chain.
+/// Ideally this code would be auto-generated from metadata, because we want to
+/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s.
+///
+/// All entries here (like pretty much in the entire file) must be kept in sync with
+/// `BridgeHubKusama` `construct_runtime`, so that we maintain SCALE-compatibility.
+#[allow(clippy::large_enum_variant)]
+#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
+pub enum Call {
+	#[cfg(test)]
+	#[codec(index = 0)]
+	System(SystemCall),
+	/// Utility pallet.
+	#[codec(index = 40)]
+	Utility(UtilityCall<Call>),
+
+	/// Polkadot bridge pallet.
+	// TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	#[codec(index = 41)]
+	BridgePolkadotGrandpa(BridgePolkadotGrandpaCall),
+	/// Polkadot parachain bridge pallet.
+	// TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	#[codec(index = 42)]
+	BridgePolkadotParachain(BridgeParachainCall),
+	/// Polkadot messages bridge pallet.
+	// TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	#[codec(index = 46)]
+	BridgePolkadotMessages(BridgePolkadotMessagesCall),
+}
+
+impl From<UtilityCall<Call>> for Call {
+	fn from(call: UtilityCall<Call>) -> Call {
+		Call::Utility(call)
+	}
+}
diff --git a/bridges/relays/client-bridge-hub-polkadot/Cargo.toml b/bridges/relays/client-bridge-hub-polkadot/Cargo.toml
new file mode 100644
index 0000000000000..dee3147eb35a3
--- /dev/null
+++ b/bridges/relays/client-bridge-hub-polkadot/Cargo.toml
@@ -0,0 +1,32 @@
+[package]
+name = "relay-bridge-hub-polkadot-client"
+version = "0.1.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2021"
+license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] }
+scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
+relay-substrate-client = { path = "../client-substrate" }
+
+# Bridge dependencies
+
+bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" }
+bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" }
+bp-header-chain = { path = "../../primitives/header-chain" }
+bp-messages = { path = "../../primitives/messages" }
+bp-parachains = { path = "../../primitives/parachains" }
+bp-kusama = { path = "../../primitives/chain-kusama" }
+bp-runtime = { path = "../../primitives/runtime" }
+
+bridge-runtime-common = { path = "../../bin/runtime-common" }
+
+# Substrate Dependencies
+
+sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
+
+[dev-dependencies]
+bp-polkadot-core = { path = "../../primitives/polkadot-core" }
+sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/bridges/relays/client-bridge-hub-polkadot/src/lib.rs b/bridges/relays/client-bridge-hub-polkadot/src/lib.rs
new file mode 100644
index 0000000000000..6428b055dd5a2
--- /dev/null
+++ b/bridges/relays/client-bridge-hub-polkadot/src/lib.rs
@@ -0,0 +1,160 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Types used to connect to the BridgeHub-Polkadot-Substrate parachain.
+
+use bp_bridge_hub_polkadot::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL};
+use bp_messages::MessageNonce;
+use bp_runtime::ChainId;
+use codec::Encode;
+use relay_substrate_client::{
+	Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet,
+	Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider,
+	UnsignedTransaction,
+};
+use sp_core::{storage::StorageKey, Pair};
+use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
+use std::time::Duration;
+
+/// Re-export runtime wrapper
+pub mod runtime_wrapper;
+pub use runtime_wrapper as runtime;
+
+/// Polkadot chain definition
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct BridgeHubPolkadot;
+
+impl UnderlyingChainProvider for BridgeHubPolkadot {
+	type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot;
+}
+
+impl Chain for BridgeHubPolkadot {
+	const ID: ChainId = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID;
+	const NAME: &'static str = "BridgeHubPolkadot";
+	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
+		bp_bridge_hub_polkadot::BEST_FINALIZED_BRIDGE_HUB_POLKADOT_HEADER_METHOD;
+	const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL;
+
+	type SignedBlock = bp_bridge_hub_polkadot::SignedBlock;
+	type Call = runtime::Call;
+}
+
+impl ChainWithBalances for BridgeHubPolkadot {
+	fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
+		bp_bridge_hub_polkadot::AccountInfoStorageMapKeyProvider::final_key(account_id)
+	}
+}
+
+impl ChainWithUtilityPallet for BridgeHubPolkadot {
+	type UtilityPallet = MockedRuntimeUtilityPallet<runtime::Call>;
+}
+
+impl ChainWithTransactions for BridgeHubPolkadot {
+	type AccountKeyPair = sp_core::sr25519::Pair;
+	type SignedTransaction = runtime::UncheckedExtrinsic;
+
+	fn sign_transaction(
+		param: SignParam<Self>,
+		unsigned: UnsignedTransaction<Self>,
+	) -> Result<Self::SignedTransaction, SubstrateError> {
+		let raw_payload = SignedPayload::new(
+			unsigned.call,
+			runtime::SignedExtension::from_params(
+				param.spec_version,
+				param.transaction_version,
+				unsigned.era,
+				param.genesis_hash,
+				unsigned.nonce,
+				unsigned.tip,
+			),
+		)?;
+
+		let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload));
+		let signer: sp_runtime::MultiSigner = param.signer.public().into();
+		let (call, extra, _) = raw_payload.deconstruct();
+
+		Ok(runtime::UncheckedExtrinsic::new_signed(
+			call,
+			signer.into_account().into(),
+			signature.into(),
+			extra,
+		))
+	}
+
+	fn is_signed(tx: &Self::SignedTransaction) -> bool {
+		tx.signature.is_some()
+	}
+
+	fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool {
+		tx.signature
+			.as_ref()
+			.map(|(address, _, _)| {
+				*address == bp_bridge_hub_polkadot::Address::Id(signer.public().into())
+			})
+			.unwrap_or(false)
+	}
+
+	fn parse_transaction(tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self>> {
+		let extra = &tx.signature.as_ref()?.2;
+		Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip()))
+	}
+}
+
+impl ChainWithMessages for BridgeHubPolkadot {
+	const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
+		bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME;
+	const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> =
+		Some(bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME);
+
+	const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
+		bp_bridge_hub_polkadot::TO_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD;
+	const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
+		bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD;
+
+	const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
+		bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
+	const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
+		bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use relay_substrate_client::TransactionEra;
+
+	#[test]
+	fn parse_transaction_works() {
+		let unsigned = UnsignedTransaction {
+			call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec()))
+				.into(),
+			nonce: 777,
+			tip: 888,
+			era: TransactionEra::immortal(),
+		};
+		let signed_transaction = BridgeHubPolkadot::sign_transaction(
+			SignParam {
+				spec_version: 42,
+				transaction_version: 50000,
+				genesis_hash: [42u8; 32].into(),
+				signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(),
+			},
+			unsigned.clone(),
+		)
+		.unwrap();
+		let parsed_transaction = BridgeHubPolkadot::parse_transaction(signed_transaction).unwrap();
+		assert_eq!(parsed_transaction, unsigned);
+	}
+}
diff --git a/bridges/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs b/bridges/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs
new file mode 100644
index 0000000000000..5afac61dbb3fc
--- /dev/null
+++ b/bridges/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs
@@ -0,0 +1,119 @@
+// Copyright 2019-2021 Parity Technologies (UK) Ltd.
+// This file is part of Parity Bridges Common.
+
+// Parity Bridges Common is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity Bridges Common is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Types that are specific to the BridgeHubPolkadot runtime.
+// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945)
+
+use codec::{Decode, Encode};
+use scale_info::TypeInfo;
+
+pub use bp_bridge_hub_polkadot::SignedExtension;
+pub use bp_header_chain::BridgeGrandpaCallOf;
+pub use bp_parachains::BridgeParachainCall;
+pub use bridge_runtime_common::messages::BridgeMessagesCallOf;
+pub use relay_substrate_client::calls::{SystemCall, UtilityCall};
+
+/// Unchecked BridgeHubPolkadot extrinsic.
+pub type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic<Call, SignedExtension>;
+
+// The indirect pallet call used to sync `Kusama` GRANDPA finality to `BHPolkadot`.
+pub type BridgeKusamaGrandpaCall = BridgeGrandpaCallOf<bp_kusama::Kusama>;
+// The indirect pallet call used to sync `BridgeHubKusama` messages to `BridgeHubPolkadot`.
+pub type BridgeKusamaMessagesCall = BridgeMessagesCallOf<bp_bridge_hub_kusama::BridgeHubKusama>;
+
+/// `BridgeHubPolkadot` Runtime `Call` enum.
+///
+/// The enum represents a subset of possible `Call`s we can send to `BridgeHubPolkadot` chain.
+/// Ideally this code would be auto-generated from metadata, because we want to
+/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s.
+///
+/// All entries here (like pretty much in the entire file) must be kept in sync with
+/// `BridgeHubPolkadot` `construct_runtime`, so that we maintain SCALE-compatibility.
+#[allow(clippy::large_enum_variant)]
+#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
+pub enum Call {
+	#[cfg(test)]
+	#[codec(index = 0)]
+	System(SystemCall),
+	/// Utility pallet.
+	#[codec(index = 40)]
+	Utility(UtilityCall<Call>),
+
+	/// Kusama bridge pallet.
+	// TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	#[codec(index = 43)]
+	BridgeKusamaGrandpa(BridgeKusamaGrandpaCall),
+	/// Kusama parachain bridge pallet.
+	// TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	#[codec(index = 44)]
+	BridgeKusamaParachain(BridgeParachainCall),
+	/// Kusama messages bridge pallet.
+	// TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	#[codec(index = 45)]
+	BridgeKusamaMessages(BridgeKusamaMessagesCall),
+}
+
+impl From<UtilityCall<Call>> for Call {
+	fn from(call: UtilityCall<Call>) -> Call {
+		Call::Utility(call)
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use bp_runtime::BasicOperatingMode;
+	use sp_consensus_grandpa::AuthorityList;
+	use sp_core::hexdisplay::HexDisplay;
+	use sp_runtime::traits::Header;
+	use std::str::FromStr;
+
+	pub type RelayBlockNumber = bp_polkadot_core::BlockNumber;
+	pub type RelayBlockHasher = bp_polkadot_core::Hasher;
+	pub type RelayBlockHeader = sp_runtime::generic::Header<RelayBlockNumber, RelayBlockHasher>;
+
+	#[test]
+	fn encode_decode_calls() {
+		let header = RelayBlockHeader::new(
+			75,
+			bp_polkadot_core::Hash::from_str(
+				"0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d",
+			)
+			.expect("invalid value"),
+			bp_polkadot_core::Hash::from_str(
+				"0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b",
+			)
+			.expect("invalid value"),
+			bp_polkadot_core::Hash::from_str(
+				"0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d",
+			)
+			.expect("invalid value"),
+			Default::default(),
+		);
+		let init_data = bp_header_chain::InitializationData {
+			header: Box::new(header),
+			authority_list: AuthorityList::default(),
+			set_id: 6,
+			operating_mode: BasicOperatingMode::Normal,
+		};
+		let call = BridgeKusamaGrandpaCall::initialize { init_data };
+		let tx = Call::BridgeKusamaGrandpa(call);
+
+		// encode call as hex string
+		let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx)));
+		assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000");
+	}
+}
diff --git a/bridges/relays/client-bridge-hub-rococo/src/lib.rs b/bridges/relays/client-bridge-hub-rococo/src/lib.rs
index 87d461b976109..bc2ec3aca41e6 100644
--- a/bridges/relays/client-bridge-hub-rococo/src/lib.rs
+++ b/bridges/relays/client-bridge-hub-rococo/src/lib.rs
@@ -44,7 +44,6 @@ impl UnderlyingChainProvider for BridgeHubRococo {
 impl Chain for BridgeHubRococo {
 	const ID: ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID;
 	const NAME: &'static str = "BridgeHubRococo";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL;
diff --git a/bridges/relays/client-bridge-hub-wococo/src/lib.rs b/bridges/relays/client-bridge-hub-wococo/src/lib.rs
index e9864bf98857a..c9acc47dd954d 100644
--- a/bridges/relays/client-bridge-hub-wococo/src/lib.rs
+++ b/bridges/relays/client-bridge-hub-wococo/src/lib.rs
@@ -44,7 +44,6 @@ impl UnderlyingChainProvider for BridgeHubWococo {
 impl Chain for BridgeHubWococo {
 	const ID: ChainId = bp_runtime::BRIDGE_HUB_WOCOCO_CHAIN_ID;
 	const NAME: &'static str = "BridgeHubWococo";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_bridge_hub_wococo::BEST_FINALIZED_BRIDGE_HUB_WOCOCO_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL;
diff --git a/bridges/relays/client-kusama/src/lib.rs b/bridges/relays/client-kusama/src/lib.rs
index 4b631b6052b79..99a52b4baf434 100644
--- a/bridges/relays/client-kusama/src/lib.rs
+++ b/bridges/relays/client-kusama/src/lib.rs
@@ -18,13 +18,16 @@
 
 use bp_kusama::AccountInfoStorageMapKeyProvider;
 use bp_runtime::ChainId;
-use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider};
+use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider};
 use sp_core::storage::StorageKey;
 use std::time::Duration;
 
 /// Kusama header id.
 pub type HeaderId = relay_utils::HeaderId<bp_kusama::Hash, bp_kusama::BlockNumber>;
 
+/// Kusama header type used in headers sync.
+pub type SyncHeader = relay_substrate_client::SyncHeader<bp_kusama::Header>;
+
 /// Kusama chain definition
 #[derive(Debug, Clone, Copy)]
 pub struct Kusama;
@@ -36,7 +39,6 @@ impl UnderlyingChainProvider for Kusama {
 impl Chain for Kusama {
 	const ID: ChainId = bp_runtime::KUSAMA_CHAIN_ID;
 	const NAME: &'static str = "Kusama";
-	const TOKEN_ID: Option<&'static str> = Some("kusama");
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -51,5 +53,8 @@ impl ChainWithBalances for Kusama {
 	}
 }
 
-/// Kusama header type used in headers sync.
-pub type SyncHeader = relay_substrate_client::SyncHeader<bp_kusama::Header>;
+impl RelayChain for Kusama {
+	const PARAS_PALLET_NAME: &'static str = bp_kusama::PARAS_PALLET_NAME;
+	// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeKusamaParachain";
+}
diff --git a/bridges/relays/client-millau/src/lib.rs b/bridges/relays/client-millau/src/lib.rs
index 1c8a0f984ef0a..ce42d004bb807 100644
--- a/bridges/relays/client-millau/src/lib.rs
+++ b/bridges/relays/client-millau/src/lib.rs
@@ -57,8 +57,6 @@ impl ChainWithMessages for Millau {
 impl Chain for Millau {
 	const ID: ChainId = bp_runtime::MILLAU_CHAIN_ID;
 	const NAME: &'static str = "Millau";
-	// Rialto token has no value, but we associate it with KSM token
-	const TOKEN_ID: Option<&'static str> = Some("kusama");
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
diff --git a/bridges/relays/client-polkadot/src/lib.rs b/bridges/relays/client-polkadot/src/lib.rs
index 08837bdcec2f6..7f8615e0cd0ef 100644
--- a/bridges/relays/client-polkadot/src/lib.rs
+++ b/bridges/relays/client-polkadot/src/lib.rs
@@ -18,13 +18,16 @@
 
 use bp_polkadot::AccountInfoStorageMapKeyProvider;
 use bp_runtime::ChainId;
-use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider};
+use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider};
 use sp_core::storage::StorageKey;
 use std::time::Duration;
 
 /// Polkadot header id.
 pub type HeaderId = relay_utils::HeaderId<bp_polkadot::Hash, bp_polkadot::BlockNumber>;
 
+/// Polkadot header type used in headers sync.
+pub type SyncHeader = relay_substrate_client::SyncHeader<bp_polkadot::Header>;
+
 /// Polkadot chain definition
 #[derive(Debug, Clone, Copy)]
 pub struct Polkadot;
@@ -36,7 +39,6 @@ impl UnderlyingChainProvider for Polkadot {
 impl Chain for Polkadot {
 	const ID: ChainId = bp_runtime::POLKADOT_CHAIN_ID;
 	const NAME: &'static str = "Polkadot";
-	const TOKEN_ID: Option<&'static str> = Some("polkadot");
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -51,5 +53,8 @@ impl ChainWithBalances for Polkadot {
 	}
 }
 
-/// Polkadot header type used in headers sync.
-pub type SyncHeader = relay_substrate_client::SyncHeader<bp_polkadot::Header>;
+impl RelayChain for Polkadot {
+	const PARAS_PALLET_NAME: &'static str = bp_polkadot::PARAS_PALLET_NAME;
+	// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945)
+	const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgePolkadotParachain";
+}
diff --git a/bridges/relays/client-rialto-parachain/src/lib.rs b/bridges/relays/client-rialto-parachain/src/lib.rs
index 5334c59d3c190..ddb54fbefc06d 100644
--- a/bridges/relays/client-rialto-parachain/src/lib.rs
+++ b/bridges/relays/client-rialto-parachain/src/lib.rs
@@ -51,8 +51,6 @@ impl UnderlyingChainProvider for RialtoParachain {
 impl Chain for RialtoParachain {
 	const ID: ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID;
 	const NAME: &'static str = "RialtoParachain";
-	// RialtoParachain token has no value, but we associate it with DOT token
-	const TOKEN_ID: Option<&'static str> = Some("polkadot");
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
diff --git a/bridges/relays/client-rialto/src/lib.rs b/bridges/relays/client-rialto/src/lib.rs
index 7fe735b4adcac..f8f696068fe90 100644
--- a/bridges/relays/client-rialto/src/lib.rs
+++ b/bridges/relays/client-rialto/src/lib.rs
@@ -42,8 +42,6 @@ impl UnderlyingChainProvider for Rialto {
 impl Chain for Rialto {
 	const ID: ChainId = bp_runtime::RIALTO_CHAIN_ID;
 	const NAME: &'static str = "Rialto";
-	// Rialto token has no value, but we associate it with DOT token
-	const TOKEN_ID: Option<&'static str> = Some("polkadot");
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
diff --git a/bridges/relays/client-rococo/src/lib.rs b/bridges/relays/client-rococo/src/lib.rs
index 5049778a5420d..ede1bf1ded4e5 100644
--- a/bridges/relays/client-rococo/src/lib.rs
+++ b/bridges/relays/client-rococo/src/lib.rs
@@ -38,7 +38,6 @@ impl UnderlyingChainProvider for Rococo {
 impl Chain for Rococo {
 	const ID: ChainId = bp_runtime::ROCOCO_CHAIN_ID;
 	const NAME: &'static str = "Rococo";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
diff --git a/bridges/relays/client-substrate/src/chain.rs b/bridges/relays/client-substrate/src/chain.rs
index 6ab353921efca..8c7dc00aa67bb 100644
--- a/bridges/relays/client-substrate/src/chain.rs
+++ b/bridges/relays/client-substrate/src/chain.rs
@@ -39,11 +39,6 @@ pub trait Chain: ChainBase + Clone {
 	const ID: ChainId;
 	/// Chain name.
 	const NAME: &'static str;
-	/// Identifier of the basic token of the chain (if applicable).
-	///
-	/// This identifier is used to fetch token price. In case of testnets, you may either
-	/// set it to `None`, or associate testnet with one of the existing tokens.
-	const TOKEN_ID: Option<&'static str>;
 	/// Name of the runtime API method that is returning best known finalized header number
 	/// and hash (as tuple).
 	///
diff --git a/bridges/relays/client-substrate/src/test_chain.rs b/bridges/relays/client-substrate/src/test_chain.rs
index d33cb1de68123..64c7590ee5250 100644
--- a/bridges/relays/client-substrate/src/test_chain.rs
+++ b/bridges/relays/client-substrate/src/test_chain.rs
@@ -53,7 +53,6 @@ impl bp_runtime::Chain for TestChain {
 impl Chain for TestChain {
 	const ID: ChainId = *b"test";
 	const NAME: &'static str = "Test";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod";
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0);
 
@@ -108,7 +107,6 @@ impl bp_runtime::UnderlyingChainProvider for TestParachain {
 impl Chain for TestParachain {
 	const ID: ChainId = *b"test";
 	const NAME: &'static str = "TestParachain";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestParachainMethod";
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0);
 
diff --git a/bridges/relays/client-westend/src/lib.rs b/bridges/relays/client-westend/src/lib.rs
index 6db8eaf95e40d..6013bfad128a5 100644
--- a/bridges/relays/client-westend/src/lib.rs
+++ b/bridges/relays/client-westend/src/lib.rs
@@ -38,7 +38,6 @@ impl UnderlyingChainProvider for Westend {
 impl Chain for Westend {
 	const ID: ChainId = bp_runtime::WESTEND_CHAIN_ID;
 	const NAME: &'static str = "Westend";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -72,7 +71,6 @@ impl UnderlyingChainProvider for Westmint {
 impl Chain for Westmint {
 	const ID: ChainId = bp_runtime::WESTMINT_CHAIN_ID;
 	const NAME: &'static str = "Westmint";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_westend::BEST_FINALIZED_WESTMINT_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
diff --git a/bridges/relays/client-wococo/src/lib.rs b/bridges/relays/client-wococo/src/lib.rs
index 582c34ef85363..2f0d6b22f9291 100644
--- a/bridges/relays/client-wococo/src/lib.rs
+++ b/bridges/relays/client-wococo/src/lib.rs
@@ -38,7 +38,6 @@ impl UnderlyingChainProvider for Wococo {
 impl Chain for Wococo {
 	const ID: ChainId = bp_runtime::WOCOCO_CHAIN_ID;
 	const NAME: &'static str = "Wococo";
-	const TOKEN_ID: Option<&'static str> = None;
 	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
 		bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
 	const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);