From ff9e2dfc7eb7c16cf03e528e8dcca3bd5f6af458 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 27 Mar 2024 19:26:57 +0100 Subject: [PATCH] Use pull event source when generating configuration with `hermes config auto` (#3920) * Use pull event source when generating configuration with `hermes config auto` * Add changelog entry --- .../ibc-relayer-cli/3913-config-auto-pull.md | 2 + crates/chain-registry/src/error.rs | 2 +- crates/chain-registry/src/querier.rs | 49 ++++++------------- crates/relayer-cli/src/chain_registry.rs | 26 +++++----- .../relayer-cli/src/commands/config/auto.rs | 10 +++- crates/relayer/src/config.rs | 2 +- 6 files changed, 39 insertions(+), 52 deletions(-) create mode 100644 .changelog/unreleased/improvements/ibc-relayer-cli/3913-config-auto-pull.md diff --git a/.changelog/unreleased/improvements/ibc-relayer-cli/3913-config-auto-pull.md b/.changelog/unreleased/improvements/ibc-relayer-cli/3913-config-auto-pull.md new file mode 100644 index 0000000000..c19c7f34d6 --- /dev/null +++ b/.changelog/unreleased/improvements/ibc-relayer-cli/3913-config-auto-pull.md @@ -0,0 +1,2 @@ +- Use RPC (pull) event source instead of WebSocket (push) when generating configuration with `hermes config auto` + ([\#3913](https://github.com/informalsystems/hermes/issues/3913)) diff --git a/crates/chain-registry/src/error.rs b/crates/chain-registry/src/error.rs index e64f3d267c..01ccf6af39 100644 --- a/crates/chain-registry/src/error.rs +++ b/crates/chain-registry/src/error.rs @@ -74,7 +74,7 @@ define_error! { .iter() .join(", "); - format!("Error finding a healthy endpoint after {} retries. Endpoints: {endpoints}", e.retries) + format!("Did not find a healthy endpoint after {} retries. Endpoints: {endpoints}", e.retries) }, UriParseError diff --git a/crates/chain-registry/src/querier.rs b/crates/chain-registry/src/querier.rs index ac5a2c385c..3102011f16 100644 --- a/crates/chain-registry/src/querier.rs +++ b/crates/chain-registry/src/querier.rs @@ -8,15 +8,14 @@ use std::str::FromStr; use async_trait::async_trait; use futures::{stream::FuturesUnordered, StreamExt}; use http::Uri; -use tokio::time::timeout; -use tokio::time::Duration; +use tendermint_rpc::HttpClient; +use tendermint_rpc::HttpClientUrl; use tracing::{debug, info}; use ibc_proto::cosmos::bank::v1beta1::query_client::QueryClient; -use tendermint_rpc::{Client, SubscriptionClient, Url, WebSocketClient}; +use tendermint_rpc::{Client, Url}; use crate::error::RegistryError; -use crate::formatter::{SimpleWebSocketFormatter, UriFormatter}; /// `QueryTypes` represents the basic types required to query a node pub trait QueryTypes { @@ -73,8 +72,8 @@ pub trait QueryContext: QueryTypes { // ----------------- RPC ------------------ -/// `SimpleHermesRpcQuerier` retrieves `HermesConfigData` by querying a list of RPC endpoints through their WebSocket API -/// and returns the result of the first endpoint to answer. +/// `SimpleHermesRpcQuerier` retrieves `HermesConfigData` by querying a list of RPC endpoints +/// through their RPC API and returns the result of the first endpoint to answer. pub struct SimpleHermesRpcQuerier; /// Data which must be retrieved from RPC endpoints for Hermes @@ -82,7 +81,6 @@ pub struct SimpleHermesRpcQuerier; pub struct HermesConfigData { pub rpc_address: Url, pub max_block_size: u64, - pub websocket: Url, // max_block_time should also be retrieved from the RPC // however it looks like it is not in the genesis file anymore } @@ -101,46 +99,31 @@ impl QueryContext for SimpleHermesRpcQuerier { RegistryError::no_healthy_rpc(chain_name) } - /// Convert the RPC url to a WebSocket url, query the endpoint, return the data from the RPC. - async fn query(rpc: Self::QueryInput) -> Result { - let websocket_addr = SimpleWebSocketFormatter::parse_or_build_address(rpc.as_str())?; + /// Query the endpoint, return the data from the RPC. + async fn query(rpc_url: Self::QueryInput) -> Result { + info!("Querying RPC server at {rpc_url}"); - info!("Querying WebSocket server at {websocket_addr}"); + let url = HttpClientUrl::from_str(&rpc_url) + .map_err(|e| RegistryError::tendermint_url_parse_error(rpc_url.clone(), e))?; - let (client, driver) = timeout( - Duration::from_secs(5), - WebSocketClient::new(websocket_addr.clone()), - ) - .await - .map_err(|e| RegistryError::websocket_time_out_error(websocket_addr.to_string(), e))? - .map_err(|e| RegistryError::websocket_connect_error(websocket_addr.to_string(), e))?; - - let driver_handle = tokio::spawn(driver.run()); + let client = HttpClient::builder(url) + .build() + .map_err(|e| RegistryError::rpc_connect_error(rpc_url.clone(), e))?; let latest_consensus_params = match client.latest_consensus_params().await { Ok(response) => response.consensus_params.block.max_bytes, Err(e) => { return Err(RegistryError::rpc_consensus_params_error( - websocket_addr.to_string(), + rpc_url.to_string(), e, )) } }; - client.close().map_err(|e| { - RegistryError::websocket_conn_close_error(websocket_addr.to_string(), e) - })?; - - driver_handle - .await - .map_err(|e| RegistryError::join_error("chain_data_join".to_string(), e))? - .map_err(|e| RegistryError::websocket_driver_error(websocket_addr.to_string(), e))?; - Ok(HermesConfigData { - rpc_address: Url::from_str(&rpc) - .map_err(|e| RegistryError::tendermint_url_parse_error(rpc, e))?, + rpc_address: Url::from_str(&rpc_url) + .map_err(|e| RegistryError::tendermint_url_parse_error(rpc_url, e))?, max_block_size: latest_consensus_params, - websocket: websocket_addr, }) } } diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index 9745312194..a0152b0af2 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -109,11 +109,6 @@ where ) .await?; - let websocket_address = - rpc_data.websocket.clone().try_into().map_err(|e| { - RegistryError::websocket_url_parse_error(rpc_data.websocket.to_string(), e) - })?; - let avg_gas_price = if let Some(fee_token) = chain_data.fees.fee_tokens.first() { fee_token.average_gas_price } else { @@ -131,9 +126,9 @@ where id: chain_data.chain_id, rpc_addr: rpc_data.rpc_address, grpc_addr: grpc_address, - event_source: EventSourceMode::Push { - url: websocket_address, - batch_delay: default::batch_delay(), + event_source: EventSourceMode::Pull { + interval: default::poll_interval(), + max_retries: default::max_retries(), }, rpc_timeout: default::rpc_timeout(), trusted_node: default::trusted_node(), @@ -191,6 +186,7 @@ where for i in 0..retries { let query_response = QuerierType::query_healthy(chain_name.to_string(), endpoints.clone()).await; + match query_response { Ok(r) => { return Ok(r); @@ -200,13 +196,13 @@ where } } } - Err(RegistryError::unhealthy_endpoints( - endpoints - .iter() - .map(|endpoint| endpoint.to_string()) - .collect(), - retries, - )) + + let endpoints = endpoints + .iter() + .map(|endpoint| endpoint.to_string()) + .collect(); + + Err(RegistryError::unhealthy_endpoints(endpoints, retries)) } /// Fetches the specified resources from the Cosmos chain registry, using the specified commit hash diff --git a/crates/relayer-cli/src/commands/config/auto.rs b/crates/relayer-cli/src/commands/config/auto.rs index 3c866ec304..dde3742428 100644 --- a/crates/relayer-cli/src/commands/config/auto.rs +++ b/crates/relayer-cli/src/commands/config/auto.rs @@ -9,7 +9,7 @@ use ibc_relayer::config::{store, ChainConfig, Config}; use std::collections::HashSet; use std::path::PathBuf; -use tracing::{info, warn}; +use tracing::{error, info, warn}; fn find_key(chain_config: &ChainConfig) -> Option { let keys = chain_config.list_keys().ok()?; @@ -115,7 +115,13 @@ impl Runnable for AutoCmd { let mut chain_configs: Vec<(String, ChainConfig)> = config_results .unwrap() .into_iter() - .filter_map(|(name, config)| config.ok().map(|c| (name, c))) + .filter_map(|(name, config)| match config { + Ok(config) => Some((name, config)), + Err(e) => { + error!("Failed to generate chain config for chain '{name}': {e}"); + None + } + }) .collect(); // Determine which chains were not fetched diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index d1ed7c14c0..973a0d400a 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -175,7 +175,7 @@ pub mod default { } pub fn poll_interval() -> Duration { - Duration::from_secs(1) + Duration::from_millis(500) } pub fn max_retries() -> u32 {