From 9da22df16b1eb866b4f9fb24951cfd8399af2b18 Mon Sep 17 00:00:00 2001
From: Svyatoslav Nikolsky <svyatonik@gmail.com>
Date: Tue, 22 Nov 2022 11:48:20 +0300
Subject: [PATCH] Complex parachain <> parachain relay (#1637)

* complex parachain <> parachain relay

* spelling
---
 .../src/cli/relay_headers_and_messages/mod.rs |  44 ++-
 .../parachain_to_parachain.rs                 | 281 ++++++++++++++++++
 .../relay_to_parachain.rs                     |  43 ++-
 .../relay_to_relay.rs                         |   8 +-
 4 files changed, 357 insertions(+), 19 deletions(-)
 create mode 100644 bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs

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 49e9c5aa156..bdc92f984da 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
@@ -23,6 +23,8 @@
 //!    `declare_chain_to_parachain_bridge_schema` for the bridge.
 //! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it.
 
+#[macro_use]
+mod parachain_to_parachain;
 #[macro_use]
 mod relay_to_relay;
 #[macro_use]
@@ -78,20 +80,26 @@ pub struct HeadersAndMessagesSharedParams {
 	pub prometheus_params: PrometheusParams,
 }
 
+/// Bridge parameters, shared by all bridge types.
 pub struct Full2WayBridgeCommonParams<
 	Left: ChainWithTransactions + CliChain,
 	Right: ChainWithTransactions + CliChain,
 > {
+	/// Shared parameters.
 	pub shared: HeadersAndMessagesSharedParams,
+	/// Parameters of the left chain.
 	pub left: BridgeEndCommonParams<Left>,
+	/// Parameters of the right chain.
 	pub right: BridgeEndCommonParams<Right>,
 
+	/// Common metric parameters.
 	pub metrics_params: MetricsParams,
 }
 
 impl<Left: ChainWithTransactions + CliChain, Right: ChainWithTransactions + CliChain>
 	Full2WayBridgeCommonParams<Left, Right>
 {
+	/// Creates new bridge parameters from its components.
 	pub fn new<L2R: MessagesCliBridge<Source = Left, Target = Right>>(
 		shared: HeadersAndMessagesSharedParams,
 		left: BridgeEndCommonParams<Left>,
@@ -105,14 +113,21 @@ impl<Left: ChainWithTransactions + CliChain, Right: ChainWithTransactions + CliC
 	}
 }
 
+/// Parameters that are associated with one side of the bridge.
 pub struct BridgeEndCommonParams<Chain: ChainWithTransactions + CliChain> {
+	/// Chain client.
 	pub client: Client<Chain>,
+	/// Transactions signer.
 	pub sign: AccountKeyPairOf<Chain>,
+	/// Transactions mortality.
 	pub transactions_mortality: Option<u32>,
+	/// Account that "owns" messages pallet.
 	pub messages_pallet_owner: Option<AccountKeyPairOf<Chain>>,
+	/// Accounts, which balances are exposed as metrics by the relay process.
 	pub accounts: Vec<TaggedAccount<AccountIdOf<Chain>>>,
 }
 
+/// All data of the bidirectional complex relay.
 struct FullBridge<
 	'a,
 	Source: ChainWithTransactions + CliChain,
@@ -136,6 +151,7 @@ where
 	AccountIdOf<Target>: From<<AccountKeyPairOf<Target> as Pair>::Public>,
 	BalanceOf<Source>: TryFrom<BalanceOf<Target>> + Into<u128>,
 {
+	/// Construct complex relay given it components.
 	fn new(
 		source: &'a mut BridgeEndCommonParams<Source>,
 		target: &'a mut BridgeEndCommonParams<Target>,
@@ -144,6 +160,7 @@ where
 		Self { source, target, metrics_params, _phantom_data: Default::default() }
 	}
 
+	/// Returns message relay parameters.
 	fn messages_relay_params(
 		&self,
 		source_to_target_headers_relay: Arc<dyn OnDemandRelay<BlockNumberOf<Source>>>,
@@ -182,6 +199,12 @@ declare_chain_cli_schema!(RialtoParachainsToMillau, rialto_parachains_to_millau)
 declare_relay_to_relay_bridge_schema!(Millau, Rialto);
 declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto);
 
+/// Base portion of the bidirectional complex relay.
+///
+/// This main purpose of extracting this trait is that in different relays the implementation
+/// of `start_on_demand_headers_relayers` method will be different. But the number of
+/// implementations is limited to relay <> relay, parachain <> relay and parachain <> parachain.
+/// This trait allows us to reuse these implementations in different bridges.
 #[async_trait]
 trait Full2WayBridgeBase: Sized + Send + Sync {
 	/// The CLI params for the bridge.
@@ -191,10 +214,13 @@ trait Full2WayBridgeBase: Sized + Send + Sync {
 	/// The right destination chain (it can be a relay or a parachain).
 	type Right: ChainWithTransactions + CliChain<KeyPair = AccountKeyPairOf<Self::Right>>;
 
+	/// Reference to common relay parameters.
 	fn common(&self) -> &Full2WayBridgeCommonParams<Self::Left, Self::Right>;
 
+	/// Mutable reference to common relay parameters.
 	fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right>;
 
+	/// Start on-demand headers relays.
 	async fn start_on_demand_headers_relayers(
 		&mut self,
 	) -> anyhow::Result<(
@@ -203,6 +229,7 @@ trait Full2WayBridgeBase: Sized + Send + Sync {
 	)>;
 }
 
+/// Bidirectional complex relay.
 #[async_trait]
 trait Full2WayBridge: Sized + Sync
 where
@@ -211,6 +238,7 @@ where
 	BalanceOf<Self::Left>: TryFrom<BalanceOf<Self::Right>> + Into<u128>,
 	BalanceOf<Self::Right>: TryFrom<BalanceOf<Self::Left>> + Into<u128>,
 {
+	/// Base portion of the bidirectional complex relay.
 	type Base: Full2WayBridgeBase<Left = Self::Left, Right = Self::Right>;
 
 	/// The left relay chain.
@@ -222,17 +250,21 @@ where
 		+ ChainWithBalances
 		+ CliChain<KeyPair = AccountKeyPairOf<Self::Right>>;
 
-	// Left to Right bridge
+	/// Left to Right bridge.
 	type L2R: MessagesCliBridge<Source = Self::Left, Target = Self::Right>;
-	// Right to Left bridge
+	/// Right to Left bridge
 	type R2L: MessagesCliBridge<Source = Self::Right, Target = Self::Left>;
 
+	/// Construct new bridge.
 	fn new(params: <Self::Base as Full2WayBridgeBase>::Params) -> anyhow::Result<Self>;
 
+	/// Reference to the base relay portion.
 	fn base(&self) -> &Self::Base;
 
+	/// Mutable reference to the base relay portion.
 	fn mut_base(&mut self) -> &mut Self::Base;
 
+	/// Creates and returns Left to Right complex relay.
 	fn left_to_right(&mut self) -> FullBridge<Self::Left, Self::Right, Self::L2R> {
 		let common = self.mut_base().mut_common();
 		FullBridge::<_, _, Self::L2R>::new(
@@ -242,6 +274,7 @@ where
 		)
 	}
 
+	/// Creates and returns Right to Left complex relay.
 	fn right_to_left(&mut self) -> FullBridge<Self::Right, Self::Left, Self::R2L> {
 		let common = self.mut_base().mut_common();
 		FullBridge::<_, _, Self::R2L>::new(
@@ -251,6 +284,7 @@ where
 		)
 	}
 
+	/// Start complex relay.
 	async fn run(&mut self) -> anyhow::Result<()> {
 		// Register standalone metrics.
 		{
@@ -324,6 +358,7 @@ where
 	}
 }
 
+/// Millau <> Rialto complex relay.
 pub struct MillauRialtoFull2WayBridge {
 	base: <Self as Full2WayBridge>::Base,
 }
@@ -349,6 +384,7 @@ impl Full2WayBridge for MillauRialtoFull2WayBridge {
 	}
 }
 
+/// Millau <> RialtoParachain complex relay.
 pub struct MillauRialtoParachainFull2WayBridge {
 	base: <Self as Full2WayBridge>::Base,
 }
@@ -374,10 +410,12 @@ impl Full2WayBridge for MillauRialtoParachainFull2WayBridge {
 	}
 }
 
-/// Start headers+messages relayer process.
+/// Complex headers+messages relay.
 #[derive(Debug, PartialEq, StructOpt)]
 pub enum RelayHeadersAndMessages {
+	/// Millau <> Rialto relay.
 	MillauRialto(MillauRialtoHeadersAndMessages),
+	/// Millau <> RialtoParachain relay.
 	MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages),
 }
 
diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs
new file mode 100644
index 00000000000..9adc8fd6624
--- /dev/null
+++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs
@@ -0,0 +1,281 @@
+// Copyright 2019-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/>.
+
+#![allow(unused_macros)] // TODO (https://github.com/paritytech/parity-bridges-common/issues/1629): remove me
+
+use async_trait::async_trait;
+use std::sync::Arc;
+
+use crate::cli::{
+	bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge},
+	relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams},
+	CliChain,
+};
+use bp_polkadot_core::parachains::ParaHash;
+use bp_runtime::BlockNumberOf;
+use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
+use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client};
+use sp_core::Pair;
+use substrate_relay_helper::{
+	finality::SubstrateFinalitySyncPipeline,
+	on_demand::{
+		headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay,
+	},
+	TaggedAccount, TransactionParams,
+};
+
+/// A base relay between two parachain from different consensus systems.
+///
+/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 2 on-demand
+/// parachain heads relay.
+pub struct ParachainToParachainBridge<
+	L2R: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
+	R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
+> {
+	/// Parameters that are shared by all bridge types.
+	pub common:
+		Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
+	/// Client of the left relay chain.
+	pub left_relay: Client<<L2R as ParachainToRelayHeadersCliBridge>::SourceRelay>,
+	/// Client of the right relay chain.
+	pub right_relay: Client<<R2L as ParachainToRelayHeadersCliBridge>::SourceRelay>,
+
+	/// Override for right_relay->left headers signer.
+	pub right_headers_to_left_transaction_params:
+		TransactionParams<AccountKeyPairOf<<R2L as CliBridgeBase>::Target>>,
+	/// Override for left_relay->right headers signer.
+	pub left_headers_to_right_transaction_params:
+		TransactionParams<AccountKeyPairOf<<L2R as CliBridgeBase>::Target>>,
+
+	/// Override for right->left parachains signer.
+	pub right_parachains_to_left_transaction_params:
+		TransactionParams<AccountKeyPairOf<<R2L as CliBridgeBase>::Target>>,
+	/// Override for left->right parachains signer.
+	pub left_parachains_to_right_transaction_params:
+		TransactionParams<AccountKeyPairOf<<L2R as CliBridgeBase>::Target>>,
+}
+
+macro_rules! declare_parachain_to_parachain_bridge_schema {
+	// left-parachain, relay-chain-of-left-parachain, right-parachain, relay-chain-of-right-parachain
+	($left_parachain:ident, $left_chain:ident, $right_parachain:ident, $right_chain:ident) => {
+		bp_runtime::paste::item! {
+			#[doc = $left_parachain ", " $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
+			#[derive(Debug, PartialEq, StructOpt)]
+			pub struct [<$left_parachain $right_parachain HeadersAndMessages>] {
+				// shared parameters
+				#[structopt(flatten)]
+				shared: HeadersAndMessagesSharedParams,
+
+				#[structopt(flatten)]
+				left: [<$left_parachain ConnectionParams>],
+				#[structopt(flatten)]
+				left_relay: [<$left_chain ConnectionParams>],
+
+				// default signer, which is always used to sign messages relay transactions on the left chain
+				#[structopt(flatten)]
+				left_sign: [<$left_parachain SigningParams>],
+				// signer used to sign parameter update transactions at the left parachain
+				#[structopt(flatten)]
+				left_messages_pallet_owner: [<$left_parachain MessagesPalletOwnerSigningParams>],
+
+				#[structopt(flatten)]
+				right: [<$right_parachain ConnectionParams>],
+				#[structopt(flatten)]
+				right_relay: [<$right_chain ConnectionParams>],
+
+				// default signer, which is always used to sign messages relay transactions on the right chain
+				#[structopt(flatten)]
+				right_sign: [<$right_parachain SigningParams>],
+				// signer used to sign parameter update transactions at the right parachain
+				#[structopt(flatten)]
+				right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>],
+
+				// override for right_relay->left-parachain headers signer
+				#[structopt(flatten)]
+				right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_parachain SigningParams>],
+				// override for left_relay->right-parachain headers signer
+				#[structopt(flatten)]
+				left_relay_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>],
+
+				// override for right->left parachains signer
+				#[structopt(flatten)]
+				right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_parachain SigningParams>],
+				// override for left->right parachains signer
+				#[structopt(flatten)]
+				left_parachains_to_right_sign_override: [<$left_chain ParachainsTo $right_parachain SigningParams>],
+			}
+
+			impl [<$left_chain $right_parachain HeadersAndMessages>] {
+				async fn into_bridge<
+					Left: ChainWithTransactions + CliChain<KeyPair = AccountKeyPairOf<Left>>,
+					LeftRelay: CliChain,
+					Right: ChainWithTransactions + CliChain<KeyPair = AccountKeyPairOf<Right>>,
+					RightRelay: CliChain,
+					L2R: CliBridgeBase<Source = Left, Target = Right>
+						+ MessagesCliBridge
+						+ ParachainToRelayHeadersCliBridge<SourceRelay = LeftRelay>,
+					R2L: CliBridgeBase<Source = Right, Target = Left>
+						+ MessagesCliBridge
+						+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
+				>(
+					self,
+				) -> anyhow::Result<RelayToParachainBridge<L2R, R2L>> {
+					Ok(ParachainToParachainBridge {
+						common: Full2WayBridgeCommonParams::new::<L2R>(
+							self.shared,
+							BridgeEndCommonParams {
+								client: self.left.into_client::<Left>().await?,
+								sign: self.left_sign.to_keypair::<Left>()?,
+								transactions_mortality: self.left_sign.transactions_mortality()?,
+								messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::<Left>()?,
+								accounts: vec![],
+							},
+							BridgeEndCommonParams {
+								client: self.right.into_client::<Right>().await?,
+								sign: self.right_sign.to_keypair::<Right>()?,
+								transactions_mortality: self.right_sign.transactions_mortality()?,
+								messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::<Right>()?,
+								accounts: vec![],
+							},
+						)?,
+						left_relay: self.left_relay.into_client::<RightRelay>().await?,
+						right_relay: self.right_relay.into_client::<RightRelay>().await?,
+						right_headers_to_left_transaction_params: self
+							.right_relay_headers_to_left_sign_override
+							.transaction_params_or::<Left, _>(&self.left_sign)?,
+						left_headers_to_right_transaction_params: self
+							.left_relay_headers_to_right_sign_override
+							.transaction_params_or::<Right, _>(&self.right_sign)?,
+						right_parachains_to_left_transaction_params: self
+							.right_parachains_to_left_sign_override
+							.transaction_params_or::<Left, _>(&self.left_sign)?,
+						left_parachains_to_right_transaction_params: self
+							.left_parachains_to_right_sign_override
+							.transaction_params_or::<Right, _>(&self.right_sign)?,
+					})
+				}
+			}
+		}
+	};
+}
+
+#[async_trait]
+impl<
+		Left: Chain<Hash = ParaHash> + ChainWithTransactions + CliChain<KeyPair = AccountKeyPairOf<Left>>,
+		Right: Chain<Hash = ParaHash>
+			+ ChainWithTransactions
+			+ CliChain<KeyPair = AccountKeyPairOf<Right>>,
+		LeftRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
+			+ CliChain,
+		RightRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
+			+ CliChain,
+		L2R: CliBridgeBase<Source = Left, Target = Right>
+			+ MessagesCliBridge
+			+ ParachainToRelayHeadersCliBridge<SourceRelay = LeftRelay>,
+		R2L: CliBridgeBase<Source = Right, Target = Left>
+			+ MessagesCliBridge
+			+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
+	> Full2WayBridgeBase for ParachainToParachainBridge<L2R, R2L>
+where
+	AccountIdOf<Left>: From<<AccountKeyPairOf<Left> as Pair>::Public>,
+	AccountIdOf<Right>: From<<AccountKeyPairOf<Right> as Pair>::Public>,
+{
+	type Params = ParachainToParachainBridge<L2R, R2L>;
+	type Left = Left;
+	type Right = Right;
+
+	fn common(&self) -> &Full2WayBridgeCommonParams<Left, Right> {
+		&self.common
+	}
+
+	fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right> {
+		&mut self.common
+	}
+
+	async fn start_on_demand_headers_relayers(
+		&mut self,
+	) -> anyhow::Result<(
+		Arc<dyn OnDemandRelay<BlockNumberOf<Self::Left>>>,
+		Arc<dyn OnDemandRelay<BlockNumberOf<Self::Right>>>,
+	)> {
+		self.common.left.accounts.push(TaggedAccount::Headers {
+			id: self.right_headers_to_left_transaction_params.signer.public().into(),
+			bridged_chain: RightRelay::NAME.to_string(),
+		});
+		self.common.left.accounts.push(TaggedAccount::Parachains {
+			id: self.right_parachains_to_left_transaction_params.signer.public().into(),
+			bridged_chain: RightRelay::NAME.to_string(),
+		});
+		self.common.right.accounts.push(TaggedAccount::Headers {
+			id: self.left_headers_to_right_transaction_params.signer.public().into(),
+			bridged_chain: Left::NAME.to_string(),
+		});
+		self.common.right.accounts.push(TaggedAccount::Parachains {
+			id: self.left_parachains_to_right_transaction_params.signer.public().into(),
+			bridged_chain: LeftRelay::NAME.to_string(),
+		});
+
+		<L2R as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
+			&self.common.right.client,
+			&self.left_headers_to_right_transaction_params,
+			self.common.right.client.can_start_version_guard(),
+		)
+		.await?;
+		<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
+			&self.common.left.client,
+			&self.right_headers_to_left_transaction_params,
+			self.common.left.client.can_start_version_guard(),
+		)
+		.await?;
+
+		let left_relay_to_right_on_demand_headers =
+			OnDemandHeadersRelay::new::<<L2R as ParachainToRelayHeadersCliBridge>::RelayFinality>(
+				self.left_relay.clone(),
+				self.common.right.client.clone(),
+				self.left_headers_to_right_transaction_params.clone(),
+				self.common.shared.only_mandatory_headers,
+			);
+		let right_relay_to_left_on_demand_headers =
+			OnDemandHeadersRelay::new::<<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality>(
+				self.right_relay.clone(),
+				self.common.left.client.clone(),
+				self.right_headers_to_left_transaction_params.clone(),
+				self.common.shared.only_mandatory_headers,
+			);
+
+		let left_to_right_on_demand_parachains = OnDemandParachainsRelay::new::<
+			<L2R as ParachainToRelayHeadersCliBridge>::ParachainFinality,
+		>(
+			self.left_relay.clone(),
+			self.common.right.client.clone(),
+			self.left_parachains_to_right_transaction_params.clone(),
+			Arc::new(left_relay_to_right_on_demand_headers),
+		);
+		let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::<
+			<R2L as ParachainToRelayHeadersCliBridge>::ParachainFinality,
+		>(
+			self.right_relay.clone(),
+			self.common.left.client.clone(),
+			self.right_parachains_to_left_transaction_params.clone(),
+			Arc::new(right_relay_to_left_on_demand_headers),
+		);
+
+		Ok((
+			Arc::new(left_to_right_on_demand_parachains),
+			Arc::new(right_to_left_on_demand_parachains),
+		))
+	}
+}
diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs
index 0990a2d2175..4070783df09 100644
--- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs
+++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs
@@ -38,21 +38,27 @@ use substrate_relay_helper::{
 	TaggedAccount, TransactionParams,
 };
 
+/// A base relay between standalone (relay) chain and a parachain from another consensus system.
+///
+/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 1 on-demand
+/// parachain heads relay.
 pub struct RelayToParachainBridge<
 	L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge,
 	R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
 > {
+	/// Parameters that are shared by all bridge types.
 	pub common:
 		Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
+	/// Client of the right relay chain.
 	pub right_relay: Client<<R2L as ParachainToRelayHeadersCliBridge>::SourceRelay>,
 
-	// override for right_relay->left headers signer
+	/// Override for right_relay->left headers signer.
 	pub right_headers_to_left_transaction_params:
 		TransactionParams<AccountKeyPairOf<<R2L as CliBridgeBase>::Target>>,
-	// override for right->left parachains signer
+	/// Override for right->left parachains signer.
 	pub right_parachains_to_left_transaction_params:
 		TransactionParams<AccountKeyPairOf<<R2L as CliBridgeBase>::Target>>,
-	// override for left->right headers signer
+	/// Override for left->right headers signer.
 	pub left_headers_to_right_transaction_params:
 		TransactionParams<AccountKeyPairOf<<L2R as CliBridgeBase>::Target>>,
 }
@@ -64,40 +70,50 @@ macro_rules! declare_relay_to_parachain_bridge_schema {
 			#[doc = $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
 			#[derive(Debug, PartialEq, StructOpt)]
 			pub struct [<$left_chain $right_parachain HeadersAndMessages>] {
+				// shared parameters
 				#[structopt(flatten)]
 				shared: HeadersAndMessagesSharedParams,
+
 				#[structopt(flatten)]
 				left: [<$left_chain ConnectionParams>],
+
 				// default signer, which is always used to sign messages relay transactions on the left chain
 				#[structopt(flatten)]
 				left_sign: [<$left_chain SigningParams>],
-				// override for right_relay->left headers signer
-				#[structopt(flatten)]
-				right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>],
-				// override for right->left parachains signer
-				#[structopt(flatten)]
-				right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>],
+				// signer used to sign parameter update transactions at the left chain
 				#[structopt(flatten)]
 				left_messages_pallet_owner: [<$left_chain MessagesPalletOwnerSigningParams>],
+
 				#[structopt(flatten)]
 				right: [<$right_parachain ConnectionParams>],
+				#[structopt(flatten)]
+				right_relay: [<$right_chain ConnectionParams>],
+
 				// default signer, which is always used to sign messages relay transactions on the right chain
 				#[structopt(flatten)]
 				right_sign: [<$right_parachain SigningParams>],
+				// signer used to sign parameter update transactions at the left chain
+				#[structopt(flatten)]
+				right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>],
+
+
+				// override for right_relay->left headers signer
+				#[structopt(flatten)]
+				right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>],
 				// override for left->right headers signer
 				#[structopt(flatten)]
 				left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>],
+
+				// override for right->left parachains signer
 				#[structopt(flatten)]
-				right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>],
-				#[structopt(flatten)]
-				right_relay: [<$right_chain ConnectionParams>],
+				right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>],
 			}
 
 			impl [<$left_chain $right_parachain HeadersAndMessages>] {
 				async fn into_bridge<
 					Left: ChainWithTransactions + CliChain<KeyPair = AccountKeyPairOf<Left>>,
 					Right: ChainWithTransactions + CliChain<KeyPair = AccountKeyPairOf<Right>>,
-					RightRelay: ChainWithTransactions + CliChain,
+					RightRelay: CliChain,
 					L2R: CliBridgeBase<Source = Left, Target = Right> + MessagesCliBridge + RelayToRelayHeadersCliBridge,
 					R2L: CliBridgeBase<Source = Right, Target = Left>
 						+ MessagesCliBridge
@@ -151,7 +167,6 @@ impl<
 			+ ChainWithTransactions
 			+ CliChain<KeyPair = AccountKeyPairOf<Right>>,
 		RightRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
-			+ ChainWithTransactions
 			+ CliChain,
 		L2R: CliBridgeBase<Source = Left, Target = Right>
 			+ MessagesCliBridge
diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs
index fb33fab8b78..bda532a2afd 100644
--- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs
+++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs
@@ -31,16 +31,20 @@ use substrate_relay_helper::{
 	TaggedAccount, TransactionParams,
 };
 
+/// A base relay between two standalone (relay) chains.
+///
+/// Such relay starts 2 messages relay and 2 on-demand header relays.
 pub struct RelayToRelayBridge<
 	L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge,
 	R2L: MessagesCliBridge + RelayToRelayHeadersCliBridge,
 > {
+	/// Parameters that are shared by all bridge types.
 	pub common:
 		Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
-	// override for right->left headers signer
+	/// Override for right->left headers signer.
 	pub right_to_left_transaction_params:
 		TransactionParams<AccountKeyPairOf<<R2L as CliBridgeBase>::Target>>,
-	// override for left->right headers signer
+	/// Override for left->right headers signer.
 	pub left_to_right_transaction_params:
 		TransactionParams<AccountKeyPairOf<<L2R as CliBridgeBase>::Target>>,
 }
-- 
GitLab