diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index d4840f4c7d11..98a0469ae4d7 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -29,7 +29,7 @@ mod relay_to_relay; mod relay_to_parachain; use async_trait::async_trait; -use std::sync::Arc; +use std::{marker::PhantomData, sync::Arc}; use structopt::StructOpt; use strum::VariantNames; @@ -55,6 +55,7 @@ use crate::{ }, declare_chain_cli_schema, }; +use bp_messages::LaneId; use bp_runtime::{BalanceOf, BlockNumberOf}; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ @@ -63,7 +64,8 @@ use relay_substrate_client::{ use relay_utils::metrics::MetricsParams; use sp_core::Pair; use substrate_relay_helper::{ - messages_lane::MessagesRelayParams, on_demand::OnDemandRelay, TaggedAccount, TransactionParams, + messages_lane::MessagesRelayParams, messages_metrics::StandaloneMessagesMetrics, + on_demand::OnDemandRelay, TaggedAccount, TransactionParams, }; /// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. @@ -95,20 +97,155 @@ pub struct Full2WayBridgeCommonParams< Right: TransactionSignScheme + CliChain, > { pub shared: HeadersAndMessagesSharedParams, + pub left: BridgeEndCommonParams, + pub right: BridgeEndCommonParams, - pub left: Client, - // default signer, which is always used to sign messages relay transactions on the left chain - pub left_sign: AccountKeyPairOf, - pub left_transactions_mortality: Option, - pub left_messages_pallet_owner: Option>, - pub at_left_accounts: Vec>>, - - pub right: Client, - // default signer, which is always used to sign messages relay transactions on the right chain - pub right_sign: AccountKeyPairOf, - pub right_transactions_mortality: Option, - pub right_messages_pallet_owner: Option>, - pub at_right_accounts: Vec>>, + pub metrics_params: MetricsParams, + pub left_to_right_metrics: StandaloneMessagesMetrics, + pub right_to_left_metrics: StandaloneMessagesMetrics, +} + +impl + Full2WayBridgeCommonParams +{ + pub fn new>( + shared: HeadersAndMessagesSharedParams, + left: BridgeEndCommonParams, + right: BridgeEndCommonParams, + ) -> anyhow::Result { + // Create metrics registry. + let metrics_params = shared.prometheus_params.clone().into(); + let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); + let left_to_right_metrics = substrate_relay_helper::messages_metrics::standalone_metrics::< + L2R::MessagesLane, + >(left.client.clone(), right.client.clone())?; + let right_to_left_metrics = left_to_right_metrics.clone().reverse(); + + Ok(Self { + shared, + left, + right, + metrics_params, + left_to_right_metrics, + right_to_left_metrics, + }) + } +} + +pub struct BridgeEndCommonParams { + pub client: Client, + pub sign: AccountKeyPairOf, + pub transactions_mortality: Option, + pub messages_pallet_owner: Option>, + pub accounts: Vec>>, +} + +struct FullBridge< + 'a, + Source: TransactionSignScheme + CliChain, + Target: TransactionSignScheme + CliChain, + Bridge: MessagesCliBridge, +> { + shared: &'a HeadersAndMessagesSharedParams, + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + metrics: &'a StandaloneMessagesMetrics, + _phantom_data: PhantomData, +} + +impl< + 'a, + Source: TransactionSignScheme + CliChain, + Target: TransactionSignScheme + CliChain, + Bridge: MessagesCliBridge, + > FullBridge<'a, Source, Target, Bridge> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, +{ + fn new( + shared: &'a HeadersAndMessagesSharedParams, + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + metrics: &'a StandaloneMessagesMetrics, + ) -> Self { + Self { shared, source, target, metrics_params, metrics, _phantom_data: Default::default() } + } + + fn start_conversion_rate_update_loop(&mut self) -> anyhow::Result<()> { + if let Some(ref messages_pallet_owner) = self.source.messages_pallet_owner { + let format_err = || { + anyhow::format_err!( + "Cannon run conversion rate updater: {} -> {}", + Target::NAME, + Source::NAME + ) + }; + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + Bridge::MessagesLane, + Source, + >( + self.source.client.clone(), + TransactionParams { + signer: messages_pallet_owner.clone(), + mortality: self.source.transactions_mortality, + }, + self.metrics + .target_to_source_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + self.metrics + .target_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + self.metrics + .source_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + ); + self.source.accounts.push(TaggedAccount::MessagesPalletOwner { + id: messages_pallet_owner.public().into(), + bridged_chain: Target::NAME.to_string(), + }); + } + Ok(()) + } + + fn messages_relay_params( + &self, + source_to_target_headers_relay: Arc>>, + target_to_source_headers_relay: Arc>>, + lane_id: LaneId, + ) -> MessagesRelayParams { + let relayer_mode = self.shared.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); + + MessagesRelayParams { + source_client: self.source.client.clone(), + source_transaction_params: TransactionParams { + signer: self.source.sign.clone(), + mortality: self.source.transactions_mortality, + }, + target_client: self.target.client.clone(), + target_transaction_params: TransactionParams { + signer: self.target.sign.clone(), + mortality: self.target.transactions_mortality, + }, + source_to_target_headers_relay: Some(source_to_target_headers_relay), + target_to_source_headers_relay: Some(target_to_source_headers_relay), + lane_id, + metrics_params: self.metrics_params.clone().disable(), + standalone_metrics: Some(self.metrics.clone()), + relay_strategy, + } + } } // All supported chains. @@ -179,195 +316,97 @@ where fn mut_base(&mut self) -> &mut Self::Base; - async fn run(&mut self) -> anyhow::Result<()> { - let left_client = self.base().common().left.clone(); - let left_transactions_mortality = self.base().common().left_transactions_mortality; - let left_sign = self.base().common().left_sign.clone(); - let left_messages_pallet_owner = self.base().common().left_messages_pallet_owner.clone(); - let right_client = self.base().common().right.clone(); - let right_transactions_mortality = self.base().common().right_transactions_mortality; - let right_sign = self.base().common().right_sign.clone(); - let right_messages_pallet_owner = self.base().common().right_messages_pallet_owner.clone(); + fn left_to_right(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::L2R>::new( + &common.shared, + &mut common.left, + &mut common.right, + &common.metrics_params, + &common.left_to_right_metrics, + ) + } - let lanes = self.base().common().shared.lane.clone(); - let relayer_mode = self.base().common().shared.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); + fn right_to_left(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::R2L>::new( + &common.shared, + &mut common.right, + &mut common.left, + &common.metrics_params, + &common.right_to_left_metrics, + ) + } - // create metrics registry and register standalone metrics - let metrics_params: MetricsParams = - self.base().common().shared.prometheus_params.clone().into(); - let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); - let left_to_right_metrics = substrate_relay_helper::messages_metrics::standalone_metrics::< - ::MessagesLane, - >(left_client.clone(), right_client.clone())?; - let right_to_left_metrics = left_to_right_metrics.clone().reverse(); - self.mut_base().mut_common().at_left_accounts.push(TaggedAccount::Messages { - id: left_sign.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }); - self.mut_base().mut_common().at_right_accounts.push(TaggedAccount::Messages { - id: right_sign.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }); + async fn run(&mut self) -> anyhow::Result<()> { + // Register standalone metrics. + { + let common = self.mut_base().mut_common(); + common.left.accounts.push(TaggedAccount::Messages { + id: common.left.sign.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }); + common.right.accounts.push(TaggedAccount::Messages { + id: common.right.sign.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }); + } // start conversion rate update loops for left/right chains - if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { - let left_client = left_client.clone(); - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Self::Right::NAME, - Self::Left::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - ::MessagesLane, - Self::Left, - >( - left_client, - TransactionParams { - signer: left_messages_pallet_owner.clone(), - mortality: left_transactions_mortality, - }, - left_to_right_metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - left_to_right_metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - left_to_right_metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - self.mut_base().mut_common().at_left_accounts.push( - TaggedAccount::MessagesPalletOwner { - id: left_messages_pallet_owner.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }, - ); - } - if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { - let right_client = right_client.clone(); - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Self::Left::NAME, - Self::Right::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - ::MessagesLane, - Self::Right, - >( - right_client, - TransactionParams { - signer: right_messages_pallet_owner.clone(), - mortality: right_transactions_mortality, - }, - right_to_left_metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - right_to_left_metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - right_to_left_metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - self.mut_base().mut_common().at_right_accounts.push( - TaggedAccount::MessagesPalletOwner { - id: right_messages_pallet_owner.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }, - ); - } + self.left_to_right().start_conversion_rate_update_loop()?; + self.right_to_left().start_conversion_rate_update_loop()?; // start on-demand header relays let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = self.mut_base().start_on_demand_headers_relayers().await?; // add balance-related metrics - let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( - left_client.clone(), - metrics_params, - &self.base().common().at_left_accounts, - ) - .await?; - let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( - right_client.clone(), - metrics_params, - &self.base().common().at_right_accounts, - ) - .await?; + { + let common = self.mut_base().mut_common(); + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + common.left.client.clone(), + &mut common.metrics_params, + &common.left.accounts, + ) + .await?; + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + common.right.client.clone(), + &mut common.metrics_params, + &common.right.accounts, + ) + .await?; + } + let lanes = self.base().common().shared.lane.clone(); // Need 2x capacity since we consider both directions for each lane let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { let lane = lane.into(); + let left_to_right_messages = substrate_relay_helper::messages_lane::run::< ::MessagesLane, - >(MessagesRelayParams { - source_client: left_client.clone(), - source_transaction_params: TransactionParams { - signer: left_sign.clone(), - mortality: left_transactions_mortality, - }, - target_client: right_client.clone(), - target_transaction_params: TransactionParams { - signer: right_sign.clone(), - mortality: right_transactions_mortality, - }, - source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), - target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params.clone().disable(), - standalone_metrics: Some(left_to_right_metrics.clone()), - relay_strategy: relay_strategy.clone(), - }) + >(self.left_to_right().messages_relay_params( + left_to_right_on_demand_headers.clone(), + right_to_left_on_demand_headers.clone(), + lane, + )) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); + message_relays.push(left_to_right_messages); + let right_to_left_messages = substrate_relay_helper::messages_lane::run::< ::MessagesLane, - >(MessagesRelayParams { - source_client: right_client.clone(), - source_transaction_params: TransactionParams { - signer: right_sign.clone(), - mortality: right_transactions_mortality, - }, - target_client: left_client.clone(), - target_transaction_params: TransactionParams { - signer: left_sign.clone(), - mortality: left_transactions_mortality, - }, - source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), - target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params.clone().disable(), - standalone_metrics: Some(right_to_left_metrics.clone()), - relay_strategy: relay_strategy.clone(), - }) + >(self.right_to_left().messages_relay_params( + right_to_left_on_demand_headers.clone(), + left_to_right_on_demand_headers.clone(), + lane, + )) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); - - message_relays.push(left_to_right_messages); message_relays.push(right_to_left_messages); } - relay_utils::relay_metrics(metrics_params) + relay_utils::relay_metrics(self.base().common().metrics_params.clone()) .expose() .await .map_err(|e| anyhow::format_err!("{}", e))?; diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 0d847141d4a6..b8f1992a2ff8 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -106,19 +106,23 @@ macro_rules! declare_relay_to_parachain_bridge_schema { self, ) -> anyhow::Result> { Ok(RelayToParachainBridge { - common: Full2WayBridgeCommonParams { - shared: self.shared, - left: self.left.into_client::().await?, - left_sign: self.left_sign.to_keypair::()?, - left_transactions_mortality: self.left_sign.transactions_mortality()?, - left_messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, - at_left_accounts: vec![], - right: self.right.into_client::().await?, - right_sign: self.right_sign.to_keypair::()?, - right_transactions_mortality: self.right_sign.transactions_mortality()?, - right_messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, - at_right_accounts: vec![], - }, + common: Full2WayBridgeCommonParams::new::( + self.shared, + BridgeEndCommonParams { + client: self.left.into_client::().await?, + sign: self.left_sign.to_keypair::()?, + transactions_mortality: self.left_sign.transactions_mortality()?, + messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + BridgeEndCommonParams { + client: self.right.into_client::().await?, + sign: self.right_sign.to_keypair::()?, + transactions_mortality: self.right_sign.transactions_mortality()?, + messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + )?, right_relay: self.right_relay.into_client::().await?, right_headers_to_left_transaction_params: self .right_relay_headers_to_left_sign_override @@ -178,43 +182,43 @@ where Arc>>, Arc>>, )> { - self.common.at_left_accounts.push(TaggedAccount::Headers { + self.common.left.accounts.push(TaggedAccount::Headers { id: self.right_headers_to_left_transaction_params.signer.public().into(), bridged_chain: RightRelay::NAME.to_string(), }); - self.common.at_left_accounts.push(TaggedAccount::Parachains { + self.common.left.accounts.push(TaggedAccount::Parachains { id: self.right_parachains_to_left_transaction_params.signer.public().into(), bridged_chain: RightRelay::NAME.to_string(), }); - self.common.at_right_accounts.push(TaggedAccount::Headers { + self.common.right.accounts.push(TaggedAccount::Headers { id: self.left_headers_to_right_transaction_params.signer.public().into(), bridged_chain: Left::NAME.to_string(), }); ::Finality::start_relay_guards( - &self.common.right, + &self.common.right.client, &self.left_headers_to_right_transaction_params, - self.common.right.can_start_version_guard(), + self.common.right.client.can_start_version_guard(), ) .await?; ::RelayFinality::start_relay_guards( - &self.common.left, + &self.common.left.client, &self.right_headers_to_left_transaction_params, - self.common.left.can_start_version_guard(), + self.common.left.client.can_start_version_guard(), ) .await?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::<::Finality>( - self.common.left.clone(), - self.common.right.clone(), + self.common.left.client.clone(), + self.common.right.client.clone(), self.left_headers_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::new::<::RelayFinality>( self.right_relay.clone(), - self.common.left.clone(), + self.common.left.client.clone(), self.right_headers_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); @@ -222,7 +226,7 @@ where ::ParachainFinality, >( self.right_relay.clone(), - self.common.left.clone(), + self.common.left.client.clone(), self.right_parachains_to_left_transaction_params.clone(), Arc::new(right_relay_to_left_on_demand_headers), ); diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index 4e9ecd2b5812..7350f903f62c 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -85,20 +85,23 @@ macro_rules! declare_relay_to_relay_bridge_schema { self, ) -> anyhow::Result> { Ok(RelayToRelayBridge { - common: Full2WayBridgeCommonParams { - shared: self.shared, - left: self.left.into_client::().await?, - left_sign: self.left_sign.to_keypair::()?, - left_transactions_mortality: self.left_sign.transactions_mortality()?, - left_messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, - at_left_accounts: vec![], - right: self.right.into_client::().await?, - right_sign: self.right_sign.to_keypair::()?, - right_transactions_mortality: self.right_sign.transactions_mortality()?, - right_messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, - at_right_accounts: vec![], - }, - + common: Full2WayBridgeCommonParams::new::( + self.shared, + BridgeEndCommonParams { + client: self.left.into_client::().await?, + sign: self.left_sign.to_keypair::()?, + transactions_mortality: self.left_sign.transactions_mortality()?, + messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + BridgeEndCommonParams { + client: self.right.into_client::().await?, + sign: self.right_sign.to_keypair::()?, + transactions_mortality: self.right_sign.transactions_mortality()?, + messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + )?, right_to_left_transaction_params: self .right_headers_to_left_sign_override .transaction_params_or::(&self.left_sign)?, @@ -145,39 +148,39 @@ where Arc>>, Arc>>, )> { - self.common.at_right_accounts.push(TaggedAccount::Headers { + self.common.right.accounts.push(TaggedAccount::Headers { id: self.left_to_right_transaction_params.signer.public().into(), bridged_chain: Self::Left::NAME.to_string(), }); - self.common.at_left_accounts.push(TaggedAccount::Headers { + self.common.left.accounts.push(TaggedAccount::Headers { id: self.right_to_left_transaction_params.signer.public().into(), bridged_chain: Self::Right::NAME.to_string(), }); ::Finality::start_relay_guards( - &self.common.right, + &self.common.right.client, &self.left_to_right_transaction_params, - self.common.right.can_start_version_guard(), + self.common.right.client.can_start_version_guard(), ) .await?; ::Finality::start_relay_guards( - &self.common.left, + &self.common.left.client, &self.right_to_left_transaction_params, - self.common.left.can_start_version_guard(), + self.common.left.client.can_start_version_guard(), ) .await?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::<::Finality>( - self.common.left.clone(), - self.common.right.clone(), + self.common.left.client.clone(), + self.common.right.client.clone(), self.left_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::<::Finality>( - self.common.right.clone(), - self.common.left.clone(), + self.common.right.client.clone(), + self.common.left.client.clone(), self.right_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); diff --git a/bridges/relays/lib-substrate-relay/src/messages_metrics.rs b/bridges/relays/lib-substrate-relay/src/messages_metrics.rs index 4210c7d981bd..805d002b65f8 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_metrics.rs @@ -273,14 +273,14 @@ pub fn standalone_metrics( /// Add relay accounts balance metrics. pub async fn add_relay_balances_metrics( client: Client, - metrics: MetricsParams, + metrics: &mut MetricsParams, relay_accounts: &Vec>>, -) -> anyhow::Result +) -> anyhow::Result<()> where BalanceOf: Into + std::fmt::Debug, { if relay_accounts.is_empty() { - return Ok(metrics) + return Ok(()) } // if `tokenDecimals` is missing from system properties, we'll be using @@ -317,7 +317,7 @@ where relay_account_balance_metric.register_and_spawn(&metrics.registry)?; } - Ok(metrics) + Ok(()) } /// Adapter for `FloatStorageValueMetric` to decode account free balance.