referrerpolicy=no-referrer-when-downgrade

substrate_relay_helper/cli/relay_headers_and_messages/
relay_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//! Relay chain to parachain relayer CLI primitives.
18
19use async_trait::async_trait;
20use std::sync::Arc;
21
22use crate::{
23	cli::{
24		bridge::{
25			CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge,
26			RelayToRelayHeadersCliBridge,
27		},
28		relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams},
29		DefaultClient,
30	},
31	finality::SubstrateFinalitySyncPipeline,
32	on_demand::{
33		headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay,
34	},
35};
36use bp_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
37use bp_polkadot_core::parachains::ParaHash;
38use relay_substrate_client::{
39	AccountIdOf, AccountKeyPairOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, Client,
40	Parachain,
41};
42use sp_core::Pair;
43
44/// A base relay between standalone (relay) chain and a parachain from another consensus system.
45///
46/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 1 on-demand
47/// parachain heads relay.
48pub struct RelayToParachainBridge<
49	L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge,
50	R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
51> where
52	<R2L as CliBridgeBase>::Source: Parachain,
53{
54	/// Parameters that are shared by all bridge types.
55	pub common:
56		Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
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 relay-to-parachain relayer.
62#[macro_export]
63macro_rules! declare_relay_to_parachain_bridge_schema {
64	// chain, parachain, relay-chain-of-parachain
65	($left_chain:ident, $right_parachain:ident, $right_chain:ident) => {
66		bp_runtime::paste::item! {
67			#[doc = $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
68			#[derive(Debug, PartialEq, Parser)]
69			pub struct [<$left_chain $right_parachain HeadersAndMessages>] {
70				// shared parameters
71				#[command(flatten)]
72				shared: HeadersAndMessagesSharedParams,
73
74				#[command(flatten)]
75				left: [<$left_chain ConnectionParams>],
76				// default signer, which is always used to sign messages relay transactions on the left chain
77				#[command(flatten)]
78				left_sign: [<$left_chain SigningParams>],
79
80				#[command(flatten)]
81				right: [<$right_parachain ConnectionParams>],
82				// default signer, which is always used to sign messages relay transactions on the right chain
83				#[command(flatten)]
84				right_sign: [<$right_parachain SigningParams>],
85
86				#[command(flatten)]
87				right_relay: [<$right_chain ConnectionParams>],
88			}
89
90			impl [<$left_chain $right_parachain HeadersAndMessages>] {
91				async fn into_bridge<
92					Left: ChainWithTransactions + ChainWithRuntimeVersion,
93					Right: ChainWithTransactions + ChainWithRuntimeVersion + Parachain,
94					RightRelay: ChainWithRuntimeVersion,
95					L2R: CliBridgeBase<Source = Left, Target = Right> + MessagesCliBridge + RelayToRelayHeadersCliBridge,
96					R2L: CliBridgeBase<Source = Right, Target = Left>
97						+ MessagesCliBridge
98						+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
99				>(
100					self,
101				) -> anyhow::Result<RelayToParachainBridge<L2R, R2L>> {
102					Ok(RelayToParachainBridge {
103						common: Full2WayBridgeCommonParams::new::<L2R>(
104							self.shared,
105							BridgeEndCommonParams {
106								client: self.left.into_client::<Left>().await?,
107								tx_params: self.left_sign.transaction_params::<Left>()?,
108								accounts: vec![],
109							},
110							BridgeEndCommonParams {
111								client: self.right.into_client::<Right>().await?,
112								tx_params: self.right_sign.transaction_params::<Right>()?,
113								accounts: vec![],
114							},
115						)?,
116						right_relay: self.right_relay.into_client::<RightRelay>().await?,
117					})
118				}
119			}
120		}
121	};
122}
123
124#[async_trait]
125impl<
126		Left: ChainWithTransactions + ChainWithRuntimeVersion,
127		Right: Chain<Hash = ParaHash> + ChainWithTransactions + ChainWithRuntimeVersion + Parachain,
128		RightRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
129			+ ChainWithRuntimeVersion,
130		L2R: CliBridgeBase<Source = Left, Target = Right>
131			+ MessagesCliBridge
132			+ RelayToRelayHeadersCliBridge,
133		R2L: CliBridgeBase<Source = Right, Target = Left>
134			+ MessagesCliBridge
135			+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
136	> Full2WayBridgeBase for RelayToParachainBridge<L2R, R2L>
137where
138	AccountIdOf<Left>: From<<AccountKeyPairOf<Left> as Pair>::Public>,
139	AccountIdOf<Right>: From<<AccountKeyPairOf<Right> as Pair>::Public>,
140{
141	type Params = RelayToParachainBridge<L2R, R2L>;
142	type Left = Left;
143	type Right = Right;
144
145	fn common(&self) -> &Full2WayBridgeCommonParams<Left, Right> {
146		&self.common
147	}
148
149	fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right> {
150		&mut self.common
151	}
152
153	async fn start_on_demand_headers_relayers(
154		&mut self,
155	) -> anyhow::Result<(
156		Arc<dyn OnDemandRelay<Self::Left, Self::Right>>,
157		Arc<dyn OnDemandRelay<Self::Right, Self::Left>>,
158	)> {
159		<L2R as RelayToRelayHeadersCliBridge>::Finality::start_relay_guards(
160			&self.common.right.client,
161			self.common.right.client.can_start_version_guard(),
162		)
163		.await?;
164		<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
165			&self.common.left.client,
166			self.common.left.client.can_start_version_guard(),
167		)
168		.await?;
169
170		let left_to_right_on_demand_headers =
171			OnDemandHeadersRelay::<<L2R as RelayToRelayHeadersCliBridge>::Finality, _, _>::new(
172				self.common.left.client.clone(),
173				self.common.right.client.clone(),
174				self.common.right.tx_params.clone(),
175				self.common.shared.headers_to_relay(),
176				None,
177			);
178		let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::<
179			<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality,
180			_,
181			_,
182		>::new(
183			self.right_relay.clone(),
184			self.common.left.client.clone(),
185			self.common.left.tx_params.clone(),
186			self.common.shared.headers_to_relay(),
187			Some(self.common.metrics_params.clone()),
188		);
189		let right_to_left_on_demand_parachains = OnDemandParachainsRelay::<
190			<R2L as ParachainToRelayHeadersCliBridge>::ParachainFinality,
191			_,
192			_,
193		>::new(
194			self.right_relay.clone(),
195			self.common.left.client.clone(),
196			self.common.left.tx_params.clone(),
197			Arc::new(right_relay_to_left_on_demand_headers),
198		);
199
200		Ok((
201			Arc::new(left_to_right_on_demand_headers),
202			Arc::new(right_to_left_on_demand_parachains),
203		))
204	}
205}