referrerpolicy=no-referrer-when-downgrade

substrate_relay_helper/cli/relay_headers_and_messages/
parachain_to_parachain.rs

1// Copyright 2019-2022 Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Parachain to parachain relayer CLI primitives.
18
19use async_trait::async_trait;
20use std::sync::Arc;
21
22use crate::{
23	cli::{
24		bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge},
25		relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams},
26		DefaultClient,
27	},
28	finality::SubstrateFinalitySyncPipeline,
29	on_demand::{
30		headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay,
31	},
32};
33use bp_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
34use bp_polkadot_core::parachains::ParaHash;
35use relay_substrate_client::{
36	AccountIdOf, AccountKeyPairOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, Client,
37	Parachain,
38};
39use sp_core::Pair;
40
41/// A base relay between two parachain from different consensus systems.
42///
43/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 2 on-demand
44/// parachain heads relay.
45pub struct ParachainToParachainBridge<
46	L2R: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
47	R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
48> where
49	<L2R as CliBridgeBase>::Source: Parachain,
50	<R2L as CliBridgeBase>::Source: Parachain,
51{
52	/// Parameters that are shared by all bridge types.
53	pub common:
54		Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
55	/// Client of the left relay chain.
56	pub left_relay: DefaultClient<<L2R as ParachainToRelayHeadersCliBridge>::SourceRelay>,
57	/// Client of the right relay chain.
58	pub right_relay: DefaultClient<<R2L as ParachainToRelayHeadersCliBridge>::SourceRelay>,
59}
60
61/// Create set of configuration objects specific to parachain-to-parachain relayer.
62#[macro_export]
63macro_rules! declare_parachain_to_parachain_bridge_schema {
64	// left-parachain, relay-chain-of-left-parachain, right-parachain, relay-chain-of-right-parachain
65	($left_parachain:ident, $left_chain:ident, $right_parachain:ident, $right_chain:ident) => {
66		bp_runtime::paste::item! {
67			#[doc = $left_parachain ", " $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
68			#[derive(Debug, PartialEq, Parser)]
69			pub struct [<$left_parachain $right_parachain HeadersAndMessages>] {
70				// shared parameters
71				#[command(flatten)]
72				shared: HeadersAndMessagesSharedParams,
73
74				#[command(flatten)]
75				left: [<$left_parachain ConnectionParams>],
76				// default signer, which is always used to sign messages relay transactions on the left chain
77				#[command(flatten)]
78				left_sign: [<$left_parachain SigningParams>],
79
80				#[command(flatten)]
81				left_relay: [<$left_chain ConnectionParams>],
82
83				#[command(flatten)]
84				right: [<$right_parachain ConnectionParams>],
85				// default signer, which is always used to sign messages relay transactions on the right chain
86				#[command(flatten)]
87				right_sign: [<$right_parachain SigningParams>],
88
89				#[command(flatten)]
90				right_relay: [<$right_chain ConnectionParams>],
91			}
92
93			impl [<$left_parachain $right_parachain HeadersAndMessages>] {
94				async fn into_bridge<
95					Left: ChainWithTransactions + ChainWithRuntimeVersion + Parachain,
96					LeftRelay: ChainWithRuntimeVersion,
97					Right: ChainWithTransactions + ChainWithRuntimeVersion + Parachain,
98					RightRelay: ChainWithRuntimeVersion,
99					L2R: $crate::cli::bridge::CliBridgeBase<Source = Left, Target = Right>
100						+ MessagesCliBridge
101						+ $crate::cli::bridge::ParachainToRelayHeadersCliBridge<SourceRelay = LeftRelay>,
102					R2L: $crate::cli::bridge::CliBridgeBase<Source = Right, Target = Left>
103						+ MessagesCliBridge
104						+ $crate::cli::bridge::ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
105				>(
106					self,
107				) -> anyhow::Result<$crate::cli::relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge<L2R, R2L>> {
108					Ok($crate::cli::relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge {
109						common: Full2WayBridgeCommonParams::new::<L2R>(
110							self.shared,
111							BridgeEndCommonParams {
112								client: self.left.into_client::<Left>().await?,
113								tx_params: self.left_sign.transaction_params::<Left>()?,
114								accounts: vec![],
115							},
116							BridgeEndCommonParams {
117								client: self.right.into_client::<Right>().await?,
118								tx_params: self.right_sign.transaction_params::<Right>()?,
119								accounts: vec![],
120							},
121						)?,
122						left_relay: self.left_relay.into_client::<LeftRelay>().await?,
123						right_relay: self.right_relay.into_client::<RightRelay>().await?,
124					})
125				}
126			}
127		}
128	};
129}
130
131#[async_trait]
132impl<
133		Left: Chain<Hash = ParaHash> + ChainWithTransactions + ChainWithRuntimeVersion + Parachain,
134		Right: Chain<Hash = ParaHash> + ChainWithTransactions + ChainWithRuntimeVersion + Parachain,
135		LeftRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
136			+ ChainWithRuntimeVersion,
137		RightRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
138			+ ChainWithRuntimeVersion,
139		L2R: CliBridgeBase<Source = Left, Target = Right>
140			+ MessagesCliBridge
141			+ ParachainToRelayHeadersCliBridge<SourceRelay = LeftRelay>,
142		R2L: CliBridgeBase<Source = Right, Target = Left>
143			+ MessagesCliBridge
144			+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
145	> Full2WayBridgeBase for ParachainToParachainBridge<L2R, R2L>
146where
147	AccountIdOf<Left>: From<<AccountKeyPairOf<Left> as Pair>::Public>,
148	AccountIdOf<Right>: From<<AccountKeyPairOf<Right> as Pair>::Public>,
149{
150	type Params = ParachainToParachainBridge<L2R, R2L>;
151	type Left = Left;
152	type Right = Right;
153
154	fn common(&self) -> &Full2WayBridgeCommonParams<Left, Right> {
155		&self.common
156	}
157
158	fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right> {
159		&mut self.common
160	}
161
162	async fn start_on_demand_headers_relayers(
163		&mut self,
164	) -> anyhow::Result<(
165		Arc<dyn OnDemandRelay<Self::Left, Self::Right>>,
166		Arc<dyn OnDemandRelay<Self::Right, Self::Left>>,
167	)> {
168		<L2R as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
169			&self.common.right.client,
170			self.common.right.client.can_start_version_guard(),
171		)
172		.await?;
173		<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
174			&self.common.left.client,
175			self.common.left.client.can_start_version_guard(),
176		)
177		.await?;
178
179		let left_relay_to_right_on_demand_headers = OnDemandHeadersRelay::<
180			<L2R as ParachainToRelayHeadersCliBridge>::RelayFinality,
181			_,
182			_,
183		>::new(
184			self.left_relay.clone(),
185			self.common.right.client.clone(),
186			self.common.right.tx_params.clone(),
187			self.common.shared.headers_to_relay(),
188			Some(self.common.metrics_params.clone()),
189		);
190		let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::<
191			<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality,
192			_,
193			_,
194		>::new(
195			self.right_relay.clone(),
196			self.common.left.client.clone(),
197			self.common.left.tx_params.clone(),
198			self.common.shared.headers_to_relay(),
199			Some(self.common.metrics_params.clone()),
200		);
201
202		let left_to_right_on_demand_parachains = OnDemandParachainsRelay::<
203			<L2R as ParachainToRelayHeadersCliBridge>::ParachainFinality,
204			_,
205			_,
206		>::new(
207			self.left_relay.clone(),
208			self.common.right.client.clone(),
209			self.common.right.tx_params.clone(),
210			Arc::new(left_relay_to_right_on_demand_headers),
211		);
212		let right_to_left_on_demand_parachains = OnDemandParachainsRelay::<
213			<R2L as ParachainToRelayHeadersCliBridge>::ParachainFinality,
214			_,
215			_,
216		>::new(
217			self.right_relay.clone(),
218			self.common.left.client.clone(),
219			self.common.left.tx_params.clone(),
220			Arc::new(right_relay_to_left_on_demand_headers),
221		);
222
223		Ok((
224			Arc::new(left_to_right_on_demand_parachains),
225			Arc::new(right_to_left_on_demand_parachains),
226		))
227	}
228}