referrerpolicy=no-referrer-when-downgrade

substrate_relay_helper/cli/
relay_parachains.rs

1// Copyright 2019-2021 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//! Primitives for exposing the parachains finality relaying functionality in the CLI.
18
19use async_std::sync::Mutex;
20use async_trait::async_trait;
21use bp_polkadot_core::BlockNumber as RelayBlockNumber;
22use bp_runtime::HeaderIdProvider;
23use clap::Parser;
24use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient};
25use relay_substrate_client::{Client, Parachain};
26use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
27use std::sync::Arc;
28
29use crate::{
30	cli::{
31		bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge},
32		chain_schema::*,
33		DefaultClient, PrometheusParams,
34	},
35	finality::SubstrateFinalitySyncPipeline,
36	parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter},
37	TransactionParams,
38};
39
40/// Parachains heads relaying params.
41#[derive(Parser)]
42pub struct RelayParachainsParams {
43	#[command(flatten)]
44	source: SourceConnectionParams,
45	#[command(flatten)]
46	target: TargetConnectionParams,
47	#[command(flatten)]
48	target_sign: TargetSigningParams,
49	/// If passed, only free headers (those, available at "free" relay chain headers)
50	/// are relayed.
51	#[arg(long)]
52	only_free_headers: bool,
53	#[command(flatten)]
54	prometheus_params: PrometheusParams,
55}
56
57/// Single parachains head relaying params.
58#[derive(Parser)]
59pub struct RelayParachainHeadParams {
60	#[command(flatten)]
61	source: SourceConnectionParams,
62	#[command(flatten)]
63	target: TargetConnectionParams,
64	#[command(flatten)]
65	target_sign: TargetSigningParams,
66	/// Prove parachain head at that relay block number. This relay header must be previously
67	/// proved to the target chain.
68	#[arg(long)]
69	at_relay_block: RelayBlockNumber,
70}
71
72/// Trait used for relaying parachains finality between 2 chains.
73#[async_trait]
74pub trait ParachainsRelayer: ParachainToRelayHeadersCliBridge
75where
76	ParachainsSource<Self::ParachainFinality, DefaultClient<Self::SourceRelay>>:
77		SourceClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
78	ParachainsTarget<
79		Self::ParachainFinality,
80		DefaultClient<Self::SourceRelay>,
81		DefaultClient<Self::Target>,
82	>: TargetClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
83	<Self as CliBridgeBase>::Source: Parachain,
84{
85	/// Start relaying parachains finality.
86	async fn relay_parachains(data: RelayParachainsParams) -> anyhow::Result<()> {
87		let source_chain_client = data.source.into_client::<Self::SourceRelay>().await?;
88		let source_client = ParachainsSource::<Self::ParachainFinality, _>::new(
89			source_chain_client.clone(),
90			Arc::new(Mutex::new(AvailableHeader::Missing)),
91		);
92
93		let target_transaction_params = TransactionParams {
94			signer: data.target_sign.to_keypair::<Self::Target>()?,
95			mortality: data.target_sign.target_transactions_mortality,
96		};
97		let target_chain_client = data.target.into_client::<Self::Target>().await?;
98		let target_client = ParachainsTarget::<Self::ParachainFinality, _, _>::new(
99			source_chain_client,
100			target_chain_client,
101			target_transaction_params,
102		);
103
104		let metrics_params: relay_utils::metrics::MetricsParams =
105			data.prometheus_params.into_metrics_params()?;
106		GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?;
107
108		Self::RelayFinality::start_relay_guards(
109			target_client.target_client(),
110			target_client.target_client().can_start_version_guard(),
111		)
112		.await?;
113
114		parachains_relay::parachains_loop::run(
115			source_client,
116			target_client,
117			metrics_params,
118			data.only_free_headers,
119			futures::future::pending(),
120		)
121		.await
122		.map_err(|e| anyhow::format_err!("{}", e))
123	}
124
125	/// Relay single parachain head. No checks are made to ensure that transaction will succeed.
126	async fn relay_parachain_head(data: RelayParachainHeadParams) -> anyhow::Result<()> {
127		let source_chain_client = data.source.into_client::<Self::SourceRelay>().await?;
128		let at_relay_block = source_chain_client
129			.header_by_number(data.at_relay_block)
130			.await
131			.map_err(|e| anyhow::format_err!("{}", e))?
132			.id();
133
134		let source_client = ParachainsSource::<Self::ParachainFinality, _>::new(
135			source_chain_client.clone(),
136			Arc::new(Mutex::new(AvailableHeader::Missing)),
137		);
138
139		let target_transaction_params = TransactionParams {
140			signer: data.target_sign.to_keypair::<Self::Target>()?,
141			mortality: data.target_sign.target_transactions_mortality,
142		};
143		let target_chain_client = data.target.into_client::<Self::Target>().await?;
144		let target_client = ParachainsTarget::<Self::ParachainFinality, _, _>::new(
145			source_chain_client,
146			target_chain_client,
147			target_transaction_params,
148		);
149
150		parachains_relay::parachains_loop::relay_single_head(
151			source_client,
152			target_client,
153			at_relay_block,
154		)
155		.await
156		.map_err(|_| anyhow::format_err!("The command has failed"))
157	}
158}