referrerpolicy=no-referrer-when-downgrade

substrate_relay_helper/cli/
relay_messages.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 messages relaying functionality in the CLI.
18
19use crate::{
20	cli::{bridge::*, chain_schema::*, HexLaneId, PrometheusParams},
21	messages::MessagesRelayParams,
22	TransactionParams,
23};
24
25use async_trait::async_trait;
26use clap::Parser;
27use sp_core::Pair;
28
29use bp_messages::MessageNonce;
30use bp_runtime::HeaderIdProvider;
31use relay_substrate_client::{
32	AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithRuntimeVersion,
33	ChainWithTransactions, Client,
34};
35use relay_utils::UniqueSaturatedInto;
36use sp_runtime::traits::TryConvert;
37
38/// Messages relaying params.
39#[derive(Parser)]
40pub struct RelayMessagesParams {
41	/// Hex-encoded lane id that should be served by the relay.
42	#[arg(long)]
43	lane: HexLaneId,
44	#[command(flatten)]
45	source: SourceConnectionParams,
46	#[command(flatten)]
47	source_sign: SourceSigningParams,
48	#[command(flatten)]
49	target: TargetConnectionParams,
50	#[command(flatten)]
51	target_sign: TargetSigningParams,
52	#[command(flatten)]
53	prometheus_params: PrometheusParams,
54}
55
56/// Messages range relaying params.
57#[derive(Parser)]
58pub struct RelayMessagesRangeParams {
59	/// Number of the source chain header that we will use to prepare a messages proof.
60	/// This header must be previously proved to the target chain.
61	#[arg(long)]
62	at_source_block: u128,
63	/// Hex-encoded lane id that should be served by the relay.
64	#[arg(long)]
65	lane: HexLaneId,
66	/// Nonce (inclusive) of the first message to relay.
67	#[arg(long)]
68	messages_start: MessageNonce,
69	/// Nonce (inclusive) of the last message to relay.
70	#[arg(long)]
71	messages_end: MessageNonce,
72	/// Whether the outbound lane state proof should be included into transaction.
73	#[arg(long)]
74	outbound_state_proof_required: bool,
75	#[command(flatten)]
76	source: SourceConnectionParams,
77	#[command(flatten)]
78	source_sign: SourceSigningParams,
79	#[command(flatten)]
80	target: TargetConnectionParams,
81	#[command(flatten)]
82	target_sign: TargetSigningParams,
83}
84
85/// Messages delivery confirmation relaying params.
86#[derive(Parser)]
87pub struct RelayMessagesDeliveryConfirmationParams {
88	/// Number of the target chain header that we will use to prepare a messages
89	/// delivery proof. This header must be previously proved to the source chain.
90	#[arg(long)]
91	at_target_block: u128,
92	/// Hex-encoded lane id that should be served by the relay.
93	#[arg(long)]
94	lane: HexLaneId,
95	#[command(flatten)]
96	source: SourceConnectionParams,
97	#[command(flatten)]
98	source_sign: SourceSigningParams,
99	#[command(flatten)]
100	target: TargetConnectionParams,
101}
102
103/// Trait used for relaying messages between 2 chains.
104#[async_trait]
105pub trait MessagesRelayer: MessagesCliBridge
106where
107	Self::Source: ChainWithTransactions + ChainWithRuntimeVersion,
108	AccountIdOf<Self::Source>: From<<AccountKeyPairOf<Self::Source> as Pair>::Public>,
109	AccountIdOf<Self::Target>: From<<AccountKeyPairOf<Self::Target> as Pair>::Public>,
110	BalanceOf<Self::Source>: TryFrom<BalanceOf<Self::Target>>,
111{
112	/// Start relaying messages.
113	async fn relay_messages(data: RelayMessagesParams) -> anyhow::Result<()> {
114		let source_client = data.source.into_client::<Self::Source>().await?;
115		let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
116		let source_transactions_mortality = data.source_sign.transactions_mortality()?;
117		let target_client = data.target.into_client::<Self::Target>().await?;
118		let target_sign = data.target_sign.to_keypair::<Self::Target>()?;
119		let target_transactions_mortality = data.target_sign.transactions_mortality()?;
120		let lane_id = HexLaneId::try_convert(data.lane).map_err(|invalid_lane_id| {
121			anyhow::format_err!("Invalid laneId: {:?}!", invalid_lane_id)
122		})?;
123
124		Self::start_relay_guards(&target_client, target_client.can_start_version_guard()).await?;
125
126		crate::messages::run::<Self::MessagesLane, _, _>(MessagesRelayParams {
127			source_client,
128			source_transaction_params: TransactionParams {
129				signer: source_sign,
130				mortality: source_transactions_mortality,
131			},
132			target_client,
133			target_transaction_params: TransactionParams {
134				signer: target_sign,
135				mortality: target_transactions_mortality,
136			},
137			source_to_target_headers_relay: None,
138			target_to_source_headers_relay: None,
139			lane_id,
140			limits: Self::maybe_messages_limits(),
141			metrics_params: data.prometheus_params.into_metrics_params()?,
142		})
143		.await
144		.map_err(|e| anyhow::format_err!("{}", e))
145	}
146
147	/// Relay a consequitive range of messages.
148	async fn relay_messages_range(data: RelayMessagesRangeParams) -> anyhow::Result<()> {
149		let source_client = data.source.into_client::<Self::Source>().await?;
150		let target_client = data.target.into_client::<Self::Target>().await?;
151		let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
152		let source_transactions_mortality = data.source_sign.transactions_mortality()?;
153		let target_sign = data.target_sign.to_keypair::<Self::Target>()?;
154		let target_transactions_mortality = data.target_sign.transactions_mortality()?;
155		let lane_id = HexLaneId::try_convert(data.lane).map_err(|invalid_lane_id| {
156			anyhow::format_err!("Invalid laneId: {:?}!", invalid_lane_id)
157		})?;
158
159		let at_source_block = source_client
160			.header_by_number(data.at_source_block.unique_saturated_into())
161			.await
162			.map_err(|e| {
163				log::trace!(
164					target: "bridge",
165					"Failed to read {} header with number {}: {e:?}",
166					Self::Source::NAME,
167					data.at_source_block,
168				);
169				anyhow::format_err!("The command has failed")
170			})?
171			.id();
172
173		crate::messages::relay_messages_range::<Self::MessagesLane>(
174			source_client,
175			target_client,
176			TransactionParams { signer: source_sign, mortality: source_transactions_mortality },
177			TransactionParams { signer: target_sign, mortality: target_transactions_mortality },
178			at_source_block,
179			lane_id,
180			data.messages_start..=data.messages_end,
181			data.outbound_state_proof_required,
182		)
183		.await
184	}
185
186	/// Relay a messages delivery confirmation.
187	async fn relay_messages_delivery_confirmation(
188		data: RelayMessagesDeliveryConfirmationParams,
189	) -> anyhow::Result<()> {
190		let source_client = data.source.into_client::<Self::Source>().await?;
191		let target_client = data.target.into_client::<Self::Target>().await?;
192		let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
193		let source_transactions_mortality = data.source_sign.transactions_mortality()?;
194		let lane_id = HexLaneId::try_convert(data.lane).map_err(|invalid_lane_id| {
195			anyhow::format_err!("Invalid laneId: {:?}!", invalid_lane_id)
196		})?;
197
198		let at_target_block = target_client
199			.header_by_number(data.at_target_block.unique_saturated_into())
200			.await
201			.map_err(|e| {
202				log::trace!(
203					target: "bridge",
204					"Failed to read {} header with number {}: {e:?}",
205					Self::Target::NAME,
206					data.at_target_block,
207				);
208				anyhow::format_err!("The command has failed")
209			})?
210			.id();
211
212		crate::messages::relay_messages_delivery_confirmation::<Self::MessagesLane>(
213			source_client,
214			target_client,
215			TransactionParams { signer: source_sign, mortality: source_transactions_mortality },
216			at_target_block,
217			lane_id,
218		)
219		.await
220	}
221
222	/// Add relay guards if required.
223	async fn start_relay_guards(
224		target_client: &impl Client<Self::Target>,
225		enable_version_guard: bool,
226	) -> relay_substrate_client::Result<()> {
227		if enable_version_guard {
228			relay_substrate_client::guard::abort_on_spec_version_change(
229				target_client.clone(),
230				target_client.simple_runtime_version().await?.spec_version,
231			);
232		}
233		Ok(())
234	}
235}