diff --git a/bridges/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/bridges/relays/bin-ethereum/src/ethereum_deploy_contract.rs index 84c12be7a7..3f9076f6db 100644 --- a/bridges/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/bridges/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -60,8 +60,8 @@ pub async fn run(params: EthereumDeployContractParams) { } = params; let result = async move { - let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::new(sub_params).await.map_err(RpcError::Substrate)?; + let eth_client = EthereumClient::try_connect(eth_params).await.map_err(RpcError::Ethereum)?; + let sub_client = SubstrateClient::::try_connect(sub_params).await.map_err(RpcError::Substrate)?; let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; let initial_set_id = sub_initial_authorities_set_id.unwrap_or(0); diff --git a/bridges/relays/bin-ethereum/src/ethereum_exchange.rs b/bridges/relays/bin-ethereum/src/ethereum_exchange.rs index 18470512b5..3111aa2de4 100644 --- a/bridges/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/bridges/relays/bin-ethereum/src/ethereum_exchange.rs @@ -335,8 +335,10 @@ async fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_has .. } = params; - let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::new(sub_params) + let eth_client = EthereumClient::try_connect(eth_params) + .await + .map_err(RpcError::Ethereum)?; + let sub_client = SubstrateClient::::try_connect(sub_params) .await .map_err(RpcError::Substrate)?; @@ -363,12 +365,8 @@ async fn run_auto_transactions_relay_loop( .. } = params; - let eth_client = EthereumClient::new(eth_params) - .await - .map_err(|err| format!("Error starting Ethereum client: {:?}", err))?; - let sub_client = SubstrateClient::::new(sub_params) - .await - .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; + let eth_client = EthereumClient::new(eth_params).await; + let sub_client = SubstrateClient::::new(sub_params).await; let eth_start_with_block_number = match eth_start_with_block_number { Some(eth_start_with_block_number) => eth_start_with_block_number, diff --git a/bridges/relays/bin-ethereum/src/ethereum_exchange_submit.rs b/bridges/relays/bin-ethereum/src/ethereum_exchange_submit.rs index 09871a0fc7..602d4f14e4 100644 --- a/bridges/relays/bin-ethereum/src/ethereum_exchange_submit.rs +++ b/bridges/relays/bin-ethereum/src/ethereum_exchange_submit.rs @@ -52,7 +52,7 @@ pub async fn run(params: EthereumExchangeSubmitParams) { } = params; let result: Result<_, String> = async move { - let eth_client = EthereumClient::new(eth_params) + let eth_client = EthereumClient::try_connect(eth_params) .await .map_err(|err| format!("error connecting to Ethereum node: {:?}", err))?; diff --git a/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs b/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs index 3dcd27e18f..111abcd86e 100644 --- a/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -270,8 +270,8 @@ pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { instance, } = params; - let eth_client = EthereumClient::new(eth_params).await?; - let sub_client = SubstrateClient::::new(sub_params).await?; + let eth_client = EthereumClient::new(eth_params).await; + let sub_client = SubstrateClient::::new(sub_params).await; let sign_sub_transactions = match sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, diff --git a/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs b/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs index 4e7e433d82..542fd41f72 100644 --- a/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -177,8 +177,8 @@ pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { metrics_params, } = params; - let eth_client = EthereumClient::new(eth_params).await?; - let sub_client = SubstrateClient::::new(sub_params).await?; + let eth_client = EthereumClient::new(eth_params).await; + let sub_client = SubstrateClient::::new(sub_params).await; let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); diff --git a/bridges/relays/bin-substrate/src/cli/mod.rs b/bridges/relays/bin-substrate/src/cli/mod.rs index 341051de5c..49bc5dc8c8 100644 --- a/bridges/relays/bin-substrate/src/cli/mod.rs +++ b/bridges/relays/bin-substrate/src/cli/mod.rs @@ -406,7 +406,7 @@ macro_rules! declare_chain_options { port: self.[<$chain_prefix _port>], secure: self.[<$chain_prefix _secure>], }) - .await? + .await ) } } diff --git a/bridges/relays/client-ethereum/Cargo.toml b/bridges/relays/client-ethereum/Cargo.toml index da4e7ef59e..64a76a6b5d 100644 --- a/bridges/relays/client-ethereum/Cargo.toml +++ b/bridges/relays/client-ethereum/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +async-std = "1.6.5" bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers" } diff --git a/bridges/relays/client-ethereum/src/client.rs b/bridges/relays/client-ethereum/src/client.rs index e2def5fb03..71dac5df6d 100644 --- a/bridges/relays/client-ethereum/src/client.rs +++ b/bridges/relays/client-ethereum/src/client.rs @@ -22,6 +22,7 @@ use crate::types::{ use crate::{ConnectionParams, Error, Result}; use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; +use relay_utils::relay_loop::RECONNECT_DELAY; use std::sync::Arc; /// Number of headers missing from the Ethereum node for us to consider node not synced. @@ -36,7 +37,28 @@ pub struct Client { impl Client { /// Create a new Ethereum RPC Client. - pub async fn new(params: ConnectionParams) -> Result { + /// + /// This function will keep connecting to given Ethereum node until connection is established + /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. + pub async fn new(params: ConnectionParams) -> Self { + loop { + match Self::try_connect(params.clone()).await { + Ok(client) => return client, + Err(error) => log::error!( + target: "bridge", + "Failed to connect to Ethereum node: {:?}. Going to retry in {}s", + error, + RECONNECT_DELAY.as_secs(), + ), + } + + async_std::task::sleep(RECONNECT_DELAY).await; + } + } + + /// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been established + /// or error otherwise. + pub async fn try_connect(params: ConnectionParams) -> Result { Ok(Self { client: Self::build_client(¶ms).await?, params, diff --git a/bridges/relays/client-substrate/src/client.rs b/bridges/relays/client-substrate/src/client.rs index 892a63d6d5..ec4220158e 100644 --- a/bridges/relays/client-substrate/src/client.rs +++ b/bridges/relays/client-substrate/src/client.rs @@ -27,6 +27,7 @@ use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use num_traits::Zero; use pallet_balances::AccountData; +use relay_utils::relay_loop::RECONNECT_DELAY; use sp_core::{storage::StorageKey, Bytes}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; @@ -77,7 +78,29 @@ impl std::fmt::Debug for Client { impl Client { /// Returns client that is able to call RPCs on Substrate node over websocket connection. - pub async fn new(params: ConnectionParams) -> Result { + /// + /// This function will keep connecting to given Sustrate node until connection is established + /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. + pub async fn new(params: ConnectionParams) -> Self { + loop { + match Self::try_connect(params.clone()).await { + Ok(client) => return client, + Err(error) => log::error!( + target: "bridge", + "Failed to connect to {} node: {:?}. Going to retry in {}s", + C::NAME, + error, + RECONNECT_DELAY.as_secs(), + ), + } + + async_std::task::sleep(RECONNECT_DELAY).await; + } + } + + /// Try to connect to Substrate node over websocket. Returns Substrate RPC client if connection + /// has been established or error otherwise. + pub async fn try_connect(params: ConnectionParams) -> Result { let client = Self::build_client(params.clone()).await?; let number: C::BlockNumber = Zero::zero();