referrerpolicy=no-referrer-when-downgrade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// 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/>.

//! Primitives for exposing the parachains finality relaying functionality in the CLI.

use async_std::sync::Mutex;
use async_trait::async_trait;
use bp_polkadot_core::BlockNumber as RelayBlockNumber;
use bp_runtime::HeaderIdProvider;
use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient};
use relay_substrate_client::{Client, Parachain};
use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
use std::sync::Arc;
use structopt::StructOpt;

use crate::{
	cli::{
		bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge},
		chain_schema::*,
		DefaultClient, PrometheusParams,
	},
	finality::SubstrateFinalitySyncPipeline,
	parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter},
	TransactionParams,
};

/// Parachains heads relaying params.
#[derive(StructOpt)]
pub struct RelayParachainsParams {
	#[structopt(flatten)]
	source: SourceConnectionParams,
	#[structopt(flatten)]
	target: TargetConnectionParams,
	#[structopt(flatten)]
	target_sign: TargetSigningParams,
	/// If passed, only free headers (those, available at "free" relay chain headers)
	/// are relayed.
	#[structopt(long)]
	only_free_headers: bool,
	#[structopt(flatten)]
	prometheus_params: PrometheusParams,
}

/// Single parachains head relaying params.
#[derive(StructOpt)]
pub struct RelayParachainHeadParams {
	#[structopt(flatten)]
	source: SourceConnectionParams,
	#[structopt(flatten)]
	target: TargetConnectionParams,
	#[structopt(flatten)]
	target_sign: TargetSigningParams,
	/// Prove parachain head at that relay block number. This relay header must be previously
	/// proved to the target chain.
	#[structopt(long)]
	at_relay_block: RelayBlockNumber,
}

/// Trait used for relaying parachains finality between 2 chains.
#[async_trait]
pub trait ParachainsRelayer: ParachainToRelayHeadersCliBridge
where
	ParachainsSource<Self::ParachainFinality, DefaultClient<Self::SourceRelay>>:
		SourceClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
	ParachainsTarget<
		Self::ParachainFinality,
		DefaultClient<Self::SourceRelay>,
		DefaultClient<Self::Target>,
	>: TargetClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
	<Self as CliBridgeBase>::Source: Parachain,
{
	/// Start relaying parachains finality.
	async fn relay_parachains(data: RelayParachainsParams) -> anyhow::Result<()> {
		let source_chain_client = data.source.into_client::<Self::SourceRelay>().await?;
		let source_client = ParachainsSource::<Self::ParachainFinality, _>::new(
			source_chain_client.clone(),
			Arc::new(Mutex::new(AvailableHeader::Missing)),
		);

		let target_transaction_params = TransactionParams {
			signer: data.target_sign.to_keypair::<Self::Target>()?,
			mortality: data.target_sign.target_transactions_mortality,
		};
		let target_chain_client = data.target.into_client::<Self::Target>().await?;
		let target_client = ParachainsTarget::<Self::ParachainFinality, _, _>::new(
			source_chain_client,
			target_chain_client,
			target_transaction_params,
		);

		let metrics_params: relay_utils::metrics::MetricsParams =
			data.prometheus_params.into_metrics_params()?;
		GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?;

		Self::RelayFinality::start_relay_guards(
			target_client.target_client(),
			target_client.target_client().can_start_version_guard(),
		)
		.await?;

		parachains_relay::parachains_loop::run(
			source_client,
			target_client,
			metrics_params,
			data.only_free_headers,
			futures::future::pending(),
		)
		.await
		.map_err(|e| anyhow::format_err!("{}", e))
	}

	/// Relay single parachain head. No checks are made to ensure that transaction will succeed.
	async fn relay_parachain_head(data: RelayParachainHeadParams) -> anyhow::Result<()> {
		let source_chain_client = data.source.into_client::<Self::SourceRelay>().await?;
		let at_relay_block = source_chain_client
			.header_by_number(data.at_relay_block)
			.await
			.map_err(|e| anyhow::format_err!("{}", e))?
			.id();

		let source_client = ParachainsSource::<Self::ParachainFinality, _>::new(
			source_chain_client.clone(),
			Arc::new(Mutex::new(AvailableHeader::Missing)),
		);

		let target_transaction_params = TransactionParams {
			signer: data.target_sign.to_keypair::<Self::Target>()?,
			mortality: data.target_sign.target_transactions_mortality,
		};
		let target_chain_client = data.target.into_client::<Self::Target>().await?;
		let target_client = ParachainsTarget::<Self::ParachainFinality, _, _>::new(
			source_chain_client,
			target_chain_client,
			target_transaction_params,
		);

		parachains_relay::parachains_loop::relay_single_head(
			source_client,
			target_client,
			at_relay_block,
		)
		.await
		.map_err(|_| anyhow::format_err!("The command has failed"))
	}
}