substrate_relay_helper/cli/
relay_messages.rs1use 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#[derive(Parser)]
40pub struct RelayMessagesParams {
41 #[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#[derive(Parser)]
58pub struct RelayMessagesRangeParams {
59 #[arg(long)]
62 at_source_block: u128,
63 #[arg(long)]
65 lane: HexLaneId,
66 #[arg(long)]
68 messages_start: MessageNonce,
69 #[arg(long)]
71 messages_end: MessageNonce,
72 #[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#[derive(Parser)]
87pub struct RelayMessagesDeliveryConfirmationParams {
88 #[arg(long)]
91 at_target_block: u128,
92 #[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#[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 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 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 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 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}