diff --git a/.changelog/unreleased/bug-fixes/ibc-chain-registry/4160-explicit-rootls-config.md b/.changelog/unreleased/bug-fixes/ibc-chain-registry/4160-explicit-rootls-config.md new file mode 100644 index 0000000000..ef68992992 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/ibc-chain-registry/4160-explicit-rootls-config.md @@ -0,0 +1,2 @@ +- add explicit root TLS configuration to gRPC clients + ([\#4160](https://github.com/informalsystems/hermes/issues/4160)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/ibc-relayer/4160-explicit-rootls-config.md b/.changelog/unreleased/bug-fixes/ibc-relayer/4160-explicit-rootls-config.md new file mode 100644 index 0000000000..8bccf778ae --- /dev/null +++ b/.changelog/unreleased/bug-fixes/ibc-relayer/4160-explicit-rootls-config.md @@ -0,0 +1,2 @@ +- Add explicit root TLS configuration to gRPC clients + ([\#4160](https://github.com/informalsystems/hermes/issues/4160)) \ No newline at end of file diff --git a/crates/chain-registry/src/querier.rs b/crates/chain-registry/src/querier.rs index 9df2504e41..3a3f1e02f6 100644 --- a/crates/chain-registry/src/querier.rs +++ b/crates/chain-registry/src/querier.rs @@ -13,6 +13,7 @@ use tendermint_rpc::HttpClientUrl; use tracing::{debug, info}; use ibc_proto::cosmos::bank::v1beta1::query_client::QueryClient; +use ibc_relayer::util::create_grpc_client; use ibc_relayer::HERMES_VERSION; use tendermint_rpc::{Client, Url}; @@ -159,7 +160,7 @@ impl QueryContext for GrpcHealthCheckQuerier { info!("Querying gRPC server at {tendermint_url}"); - QueryClient::connect(uri) + create_grpc_client(uri, QueryClient::new) .await .map_err(|_| RegistryError::unable_to_connect_with_grpc())?; diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index 43fdbaf620..338a7f9af1 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -107,6 +107,7 @@ use crate::light_client::tendermint::LightClient as TmLightClient; use crate::light_client::{LightClient, Verified}; use crate::misbehaviour::MisbehaviourEvidence; use crate::util::compat_mode::compat_mode_from_version; +use crate::util::create_grpc_client; use crate::util::pretty::PrettySlice; use crate::util::pretty::{ PrettyIdentifiedChannel, PrettyIdentifiedClientState, PrettyIdentifiedConnection, @@ -374,13 +375,10 @@ impl CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_ccv_consumer_chain_params"); - let mut client = self - .block_on( - ibc_proto::interchain_security::ccv::consumer::v1::query_client::QueryClient::connect( - self.grpc_addr.clone() - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::interchain_security::ccv::consumer::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1228,13 +1226,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_clients"); - let mut client = self - .block_on( - ibc_proto::ibc::core::client::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::client::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1419,13 +1414,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_client_connections"); - let mut client = self - .block_on( - ibc_proto::ibc::core::connection::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::connection::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1465,13 +1457,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_connections"); - let mut client = self - .block_on( - ibc_proto::ibc::core::connection::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::connection::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1523,10 +1512,11 @@ impl ChainEndpoint for CosmosSdkChain { use ibc_proto::ibc::core::connection::v1 as connection; use tonic::IntoRequest; - let mut client = - connection::query_client::QueryClient::connect(chain.grpc_addr.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client( + chain.grpc_addr.clone(), + connection::query_client::QueryClient::new, + ) + .await?; client = client.max_decoding_message_size( chain.config().max_grpc_decoding_size.get_bytes() as usize, @@ -1604,13 +1594,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_connection_channels"); - let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1676,13 +1663,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_channels"); - let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1800,13 +1784,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_channel_client_state"); - let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1871,17 +1852,15 @@ impl ChainEndpoint for CosmosSdkChain { crate::telemetry!(query, self.id(), "query_packet_commitments"); let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) + .block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + )) .map(|client| { client.max_decoding_message_size( self.config().max_grpc_decoding_size.get_bytes() as usize ) - }) - .map_err(Error::grpc_transport)?; + })?; if request.pagination.is_enabled() { let mut results = Vec::new(); @@ -2033,13 +2012,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_unreceived_packets"); - let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -2109,17 +2085,15 @@ impl ChainEndpoint for CosmosSdkChain { } let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) + .block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + )) .map(|client| { client.max_decoding_message_size( self.config().max_grpc_decoding_size.get_bytes() as usize ) - }) - .map_err(Error::grpc_transport)?; + })?; if request.pagination.is_enabled() { let mut results = Vec::new(); @@ -2229,13 +2203,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_unreceived_acknowledgements"); - let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -2570,12 +2541,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_consumer_chains"); - let mut client = self.block_on( - ibc_proto::interchain_security::ccv::provider::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::interchain_security::ccv::provider::v1::query_client::QueryClient::new, + ))?; let request = tonic::Request::new( ibc_proto::interchain_security::ccv::provider::v1::QueryConsumerChainsRequest {}, diff --git a/crates/relayer/src/chain/cosmos/query/account.rs b/crates/relayer/src/chain/cosmos/query/account.rs index e24c414ff7..aeafea7529 100644 --- a/crates/relayer/src/chain/cosmos/query/account.rs +++ b/crates/relayer/src/chain/cosmos/query/account.rs @@ -7,6 +7,7 @@ use tracing::info; use crate::chain::cosmos::types::account::Account; use crate::config::default::max_grpc_decoding_size; use crate::error::Error; +use crate::util::create_grpc_client; /// Get a `&mut Account` from an `&mut Option` if it is `Some(Account)`. /// Otherwise query for the account information, update the `Option` to `Some`, @@ -54,9 +55,7 @@ pub async fn query_account( grpc_address: &Uri, account_address: &str, ) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/balance.rs b/crates/relayer/src/chain/cosmos/query/balance.rs index 114bd27e74..c197b94331 100644 --- a/crates/relayer/src/chain/cosmos/query/balance.rs +++ b/crates/relayer/src/chain/cosmos/query/balance.rs @@ -7,6 +7,7 @@ use ibc_proto::cosmos::bank::v1beta1::{ use crate::account::Balance; use crate::config::default::max_grpc_decoding_size; use crate::error::Error; +use crate::util::create_grpc_client; /// Uses the GRPC client to retrieve the account balance for a specific denom pub async fn query_balance( @@ -14,9 +15,7 @@ pub async fn query_balance( account_address: &str, denom: &str, ) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -47,9 +46,7 @@ pub async fn query_all_balances( grpc_address: &Uri, account_address: &str, ) -> Result, Error> { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/connection.rs b/crates/relayer/src/chain/cosmos/query/connection.rs index 34c939a36d..2fbfe29650 100644 --- a/crates/relayer/src/chain/cosmos/query/connection.rs +++ b/crates/relayer/src/chain/cosmos/query/connection.rs @@ -6,12 +6,11 @@ use ibc_proto::ibc::core::connection::v1::QueryConnectionParamsRequest; use crate::config::default::max_grpc_decoding_size; use crate::error::Error; +use crate::util::create_grpc_client; /// Uses the GRPC client to retrieve the connection params pub async fn query_connection_params(grpc_address: &Uri) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/consensus_state.rs b/crates/relayer/src/chain/cosmos/query/consensus_state.rs index 538b5cb140..3f95b47013 100644 --- a/crates/relayer/src/chain/cosmos/query/consensus_state.rs +++ b/crates/relayer/src/chain/cosmos/query/consensus_state.rs @@ -7,6 +7,7 @@ use crate::chain::requests::{QueryConsensusStateHeightsRequest, QueryConsensusSt use crate::config::default::max_grpc_decoding_size; use crate::consensus_state::AnyConsensusStateWithHeight; use crate::error::Error; +use crate::util::create_grpc_client; use crate::util::pretty::{PrettyConsensusStateWithHeight, PrettyHeight}; /// Performs a `QueryConsensusStateHeightsRequest` gRPC query to fetch all the consensus state @@ -36,10 +37,11 @@ pub async fn query_consensus_state_heights( .contains("unknown method ConsensusStateHeights") } - let mut client = - ibc_proto::ibc::core::client::v1::query_client::QueryClient::connect(grpc_addr.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client( + grpc_addr.clone(), + ibc_proto::ibc::core::client::v1::query_client::QueryClient::new, + ) + .await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -105,10 +107,11 @@ pub async fn query_consensus_states( } ); - let mut client = - ibc_proto::ibc::core::client::v1::query_client::QueryClient::connect(grpc_addr.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client( + grpc_addr.clone(), + ibc_proto::ibc::core::client::v1::query_client::QueryClient::new, + ) + .await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/denom_trace.rs b/crates/relayer/src/chain/cosmos/query/denom_trace.rs index a0ef33cff0..050aea8c48 100644 --- a/crates/relayer/src/chain/cosmos/query/denom_trace.rs +++ b/crates/relayer/src/chain/cosmos/query/denom_trace.rs @@ -7,12 +7,11 @@ use ibc_proto::ibc::applications::transfer::v1::{ use crate::config::default::max_grpc_decoding_size; use crate::denom::DenomTrace; use crate::error::Error; +use crate::util::create_grpc_client; // Uses the GRPC client to retrieve the denom trace for a specific hash pub async fn query_denom_trace(grpc_address: &Uri, hash: &str) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/fee.rs b/crates/relayer/src/chain/cosmos/query/fee.rs index fab58fcc2a..e59e70bc41 100644 --- a/crates/relayer/src/chain/cosmos/query/fee.rs +++ b/crates/relayer/src/chain/cosmos/query/fee.rs @@ -13,15 +13,14 @@ use tonic::Code; use crate::config::default::max_grpc_decoding_size; use crate::error::Error; +use crate::util::create_grpc_client; pub async fn query_counterparty_payee( grpc_address: &Uri, channel_id: &ChannelId, address: &Signer, ) -> Result, Error> { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -53,9 +52,7 @@ pub async fn query_incentivized_packets( channel_id: &ChannelId, port_id: &PortId, ) -> Result, Error> { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -87,9 +84,7 @@ pub async fn query_incentivized_packet( grpc_address: &Uri, request: QueryIncentivizedPacketRequest, ) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/simulate.rs b/crates/relayer/src/chain/cosmos/simulate.rs index 0cb142d698..c48d3027a3 100644 --- a/crates/relayer/src/chain/cosmos/simulate.rs +++ b/crates/relayer/src/chain/cosmos/simulate.rs @@ -4,6 +4,7 @@ use tonic::codegen::http::Uri; use crate::config::default::max_grpc_decoding_size; use crate::error::Error; +use crate::util::create_grpc_client; pub async fn send_tx_simulate(grpc_address: &Uri, tx: Tx) -> Result { let mut tx_bytes = vec![]; @@ -15,9 +16,7 @@ pub async fn send_tx_simulate(grpc_address: &Uri, tx: Tx) -> Result ] |e| { format!("failed while fetching version info from endpoint {0} on the gRPC interface of chain {1}:{2}", e.endpoint, e.chain_id, e.address) diff --git a/crates/relayer/src/util.rs b/crates/relayer/src/util.rs index 852764ca50..765792e92b 100644 --- a/crates/relayer/src/util.rs +++ b/crates/relayer/src/util.rs @@ -15,3 +15,18 @@ pub mod retry; pub mod seq_range; pub mod stream; pub mod task; + +/// Helper function to create a gRPC client. +pub async fn create_grpc_client( + grpc_addr: tonic::transport::Uri, + client_constructor: impl FnOnce(tonic::transport::Channel) -> T, +) -> Result { + let tls_config = tonic::transport::ClientTlsConfig::new().with_native_roots(); + let channel = tonic::transport::Channel::builder(grpc_addr) + .tls_config(tls_config) + .map_err(crate::error::Error::grpc_transport)? + .connect() + .await + .map_err(crate::error::Error::grpc_transport)?; + Ok(client_constructor(channel)) +}