diff --git a/relayer-cli/src/commands/create/channel.rs b/relayer-cli/src/commands/create/channel.rs index fc5df65204..c4973ded8b 100644 --- a/relayer-cli/src/commands/create/channel.rs +++ b/relayer-cli/src/commands/create/channel.rs @@ -131,7 +131,7 @@ impl CreateChannelCommand { // Query the connection end. let height = Height::new(chain_a.id().version(), 0); let conn_end = chain_a - .query_connection(connection_a_id, height) + .query_connection(connection_a_id) .unwrap_or_else(exit_with_unrecoverable_error); // Query the client state, obtain the identifier of chain b. diff --git a/relayer-cli/src/commands/query/connection.rs b/relayer-cli/src/commands/query/connection.rs index e549fa2f62..eaea761a92 100644 --- a/relayer-cli/src/commands/query/connection.rs +++ b/relayer-cli/src/commands/query/connection.rs @@ -22,9 +22,6 @@ pub struct QueryConnectionEndCmd { #[options(free, required, help = "identifier of the connection to query")] connection_id: ConnectionId, - - #[options(help = "height of the state to query", short = "h")] - height: Option, } // cargo run --bin hermes -- query connection end ibc-test connectionidone --height 3 @@ -48,8 +45,7 @@ impl Runnable for QueryConnectionEndCmd { let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); - let height = ibc::Height::new(chain.id().version(), self.height.unwrap_or(0_u64)); - let res = chain.query_connection(&self.connection_id, height); + let res = chain.query_connection(&self.connection_id); match res { Ok(connection_end) => { if connection_end.state_matches(&State::Uninitialized) { diff --git a/relayer-cli/src/commands/tx/channel.rs b/relayer-cli/src/commands/tx/channel.rs index 47476a45f6..a720c0abf1 100644 --- a/relayer-cli/src/commands/tx/channel.rs +++ b/relayer-cli/src/commands/tx/channel.rs @@ -4,7 +4,6 @@ use ibc::events::IbcEvent; use ibc::ics03_connection::connection::ConnectionEnd; use ibc::ics04_channel::channel::Order; use ibc::ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}; -use ibc::Height; use ibc_relayer::channel::{Channel, ChannelSide}; use crate::cli_utils::ChainHandlePair; @@ -23,10 +22,7 @@ macro_rules! tx_chan_cmd { }; // Retrieve the connection - let dst_connection = match chains - .dst - .query_connection(&$self.dst_conn_id, Height::default()) - { + let dst_connection = match chains.dst.query_connection(&$self.dst_conn_id) { Ok(connection) => connection, Err(e) => return Output::error(format!("{}", e)).exit(), }; diff --git a/relayer-cli/src/commands/tx/transfer.rs b/relayer-cli/src/commands/tx/transfer.rs index 65569dc175..d8c8ac24dc 100644 --- a/relayer-cli/src/commands/tx/transfer.rs +++ b/relayer-cli/src/commands/tx/transfer.rs @@ -185,7 +185,7 @@ impl Runnable for TxIcs20MsgTransferCmd { }; let conn_end = src_chain - .query_connection(conn_id, Height::zero()) + .query_connection(conn_id) .unwrap_or_else(exit_with_unrecoverable_error); debug!("connection hop underlying the channel: {:?}", conn_end); diff --git a/relayer/src/chain.rs b/relayer/src/chain.rs index 5b0ee833e6..aeacfdada7 100644 --- a/relayer/src/chain.rs +++ b/relayer/src/chain.rs @@ -168,11 +168,7 @@ pub trait Chain: Sized { request: QueryClientConnectionsRequest, ) -> Result, Error>; - fn query_connection( - &self, - connection_id: &ConnectionId, - height: ICSHeight, - ) -> Result; + fn query_connection(&self, connection_id: &ConnectionId) -> Result; /// Performs a query to retrieve the identifiers of all channels associated with a connection. fn query_connection_channels( diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index a58145e830..6bb6b9af43 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -18,6 +18,7 @@ use tendermint_rpc::query::Query; use tendermint_rpc::{endpoint::broadcast::tx_commit::Response, Client, HttpClient, Order}; use tokio::runtime::Runtime as TokioRuntime; use tonic::codegen::http::Uri; +use tonic::Code; use ibc::downcast; use ibc::events::{from_tx_response_event, IbcEvent}; @@ -314,6 +315,47 @@ impl CosmosSdkChain { Ok((proof, height)) } + + async fn do_query_connection( + &self, + connection_id: &ConnectionId, + ) -> Result { + use ibc_proto::ibc::core::connection::v1 as connection; + + let mut client = connection::query_client::QueryClient::connect(self.grpc_addr.clone()) + .await + .map_err(|e| Kind::Grpc.context(e))?; + + let response = client + .connection(connection::QueryConnectionRequest { + connection_id: connection_id.to_string(), + }) + .await + .map_err(|e| { + if e.code() == Code::NotFound { + Kind::ConnNotFound(connection_id.clone()).into() + } else { + Kind::Grpc.context(e) + } + })?; + + match response.into_inner().connection { + Some(raw_connection) => { + let connection_end = raw_connection + .try_into() + .map_err(|e| Kind::Grpc.context(e))?; + + Ok(connection_end) + } + None => { + // When no connection is found, the GRPC call itself should return + // the NotFound error code. Nevertheless even if the call is successful, + // the connection field may not be present, because in protobuf3 + // everything is optional. + Err(Kind::ConnNotFound(connection_id.clone()).into()) + } + } + } } impl Chain for CosmosSdkChain { @@ -745,16 +787,8 @@ impl Chain for CosmosSdkChain { Ok(ids) } - fn query_connection( - &self, - connection_id: &ConnectionId, - height: ICSHeight, - ) -> Result { - let res = self.query(Path::Connections(connection_id.clone()), height, false)?; - let connection_end = ConnectionEnd::decode_vec(&res.value) - .map_err(|e| Kind::Query(format!("connection '{}'", connection_id)).context(e))?; - - Ok(connection_end) + fn query_connection(&self, connection_id: &ConnectionId) -> Result { + self.block_on(async { self.do_query_connection(connection_id).await }) } fn query_connection_channels( diff --git a/relayer/src/chain/counterparty.rs b/relayer/src/chain/counterparty.rs index 958bc9b2ff..6f0293e1fb 100644 --- a/relayer/src/chain/counterparty.rs +++ b/relayer/src/chain/counterparty.rs @@ -64,7 +64,7 @@ pub fn channel_connection_client( .ok_or_else(|| Error::MissingConnectionHops(channel_id.clone(), chain.id()))?; let connection_end = chain - .query_connection(&connection_id, Height::zero()) + .query_connection(&connection_id) .map_err(|e| Error::QueryFailed(format!("{}", e)))?; if !connection_end.is_open() { diff --git a/relayer/src/chain/handle.rs b/relayer/src/chain/handle.rs index 7dd282c9f9..effc347465 100644 --- a/relayer/src/chain/handle.rs +++ b/relayer/src/chain/handle.rs @@ -202,7 +202,6 @@ pub enum ChainRequest { QueryConnection { connection_id: ConnectionId, - height: Height, reply_to: ReplyTo, }, @@ -355,11 +354,7 @@ pub trait ChainHandle: DynClone + Send + Sync + Debug { fn query_compatible_versions(&self) -> Result, Error>; - fn query_connection( - &self, - connection_id: &ConnectionId, - height: Height, - ) -> Result; + fn query_connection(&self, connection_id: &ConnectionId) -> Result; fn query_connection_channels( &self, diff --git a/relayer/src/chain/handle/prod.rs b/relayer/src/chain/handle/prod.rs index 6f7a4bb551..f6fba90190 100644 --- a/relayer/src/chain/handle/prod.rs +++ b/relayer/src/chain/handle/prod.rs @@ -178,14 +178,9 @@ impl ChainHandle for ProdChainHandle { self.send(|reply_to| ChainRequest::QueryCompatibleVersions { reply_to }) } - fn query_connection( - &self, - connection_id: &ConnectionId, - height: Height, - ) -> Result { + fn query_connection(&self, connection_id: &ConnectionId) -> Result { self.send(|reply_to| ChainRequest::QueryConnection { connection_id: connection_id.clone(), - height, reply_to, }) } diff --git a/relayer/src/chain/mock.rs b/relayer/src/chain/mock.rs index 3a8fcf661a..18d560e967 100644 --- a/relayer/src/chain/mock.rs +++ b/relayer/src/chain/mock.rs @@ -159,11 +159,7 @@ impl Chain for MockChain { unimplemented!() } - fn query_connection( - &self, - _connection_id: &ConnectionId, - _height: Height, - ) -> Result { + fn query_connection(&self, _connection_id: &ConnectionId) -> Result { unimplemented!() } diff --git a/relayer/src/chain/runtime.rs b/relayer/src/chain/runtime.rs index 33a5bcc05f..48f9a63c3c 100644 --- a/relayer/src/chain/runtime.rs +++ b/relayer/src/chain/runtime.rs @@ -267,8 +267,8 @@ impl ChainRuntime { self.query_compatible_versions(reply_to)? }, - Ok(ChainRequest::QueryConnection { connection_id, height, reply_to }) => { - self.query_connection(connection_id, height, reply_to)? + Ok(ChainRequest::QueryConnection { connection_id, reply_to }) => { + self.query_connection(connection_id, reply_to)? }, Ok(ChainRequest::QueryConnectionChannels { request, reply_to }) => { @@ -615,10 +615,9 @@ impl ChainRuntime { fn query_connection( &self, connection_id: ConnectionId, - height: Height, reply_to: ReplyTo, ) -> Result<(), Error> { - let connection_end = self.chain.query_connection(&connection_id, height); + let connection_end = self.chain.query_connection(&connection_id); reply_to.send(connection_end).map_err(Kind::channel)?; diff --git a/relayer/src/channel.rs b/relayer/src/channel.rs index 481d8d9c8f..3519ecf17e 100644 --- a/relayer/src/channel.rs +++ b/relayer/src/channel.rs @@ -175,7 +175,7 @@ impl Channel { .map_err(|e| ChannelError::QueryError(counterparty_chain.id(), e))?; let connection_id = channel_event_attributes.connection_id.clone(); - let connection = chain.query_connection(&connection_id, Height::zero())?; + let connection = chain.query_connection(&connection_id)?; let connection_counterparty = connection.counterparty(); let counterparty_connection_id = connection_counterparty @@ -223,7 +223,7 @@ impl Channel { WorkerChannelError::MissingConnectionHops(channel.src_channel_id.clone(), chain.id()) })?; - let a_connection = chain.query_connection(&a_connection_id, Height::zero())?; + let a_connection = chain.query_connection(&a_connection_id)?; let b_connection_id = a_connection .counterparty() .connection_id() @@ -703,7 +703,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id(), Height::zero()) + .query_connection(self.dst_connection_id()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self @@ -806,7 +806,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id(), Height::zero()) + .query_connection(self.dst_connection_id()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self @@ -897,7 +897,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id(), Height::zero()) + .query_connection(self.dst_connection_id()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self @@ -1039,7 +1039,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id(), Height::zero()) + .query_connection(self.dst_connection_id()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self diff --git a/relayer/src/connection.rs b/relayer/src/connection.rs index b9fb549418..260aaf0e62 100644 --- a/relayer/src/connection.rs +++ b/relayer/src/connection.rs @@ -17,7 +17,6 @@ use ibc::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry; use ibc::ics24_host::identifier::{ChainId, ClientId, ConnectionId}; use ibc::timestamp::ZERO_DURATION; use ibc::tx_msg::Msg; -use ibc::Height as ICSHeight; use crate::chain::handle::ChainHandle; use crate::error::Error; @@ -290,11 +289,11 @@ impl Connection { counter += 1; // Continue loop if query error - let a_connection = a_chain.query_connection(&self.src_connection_id(), Height::zero()); + let a_connection = a_chain.query_connection(&self.src_connection_id()); if a_connection.is_err() { continue; } - let b_connection = b_chain.query_connection(&self.dst_connection_id(), Height::zero()); + let b_connection = b_chain.query_connection(&self.dst_connection_id()); if b_connection.is_err() { continue; } @@ -389,7 +388,7 @@ impl Connection { // Retrieve existing connection if any let dst_connection = self .dst_chain() - .query_connection(self.dst_connection_id(), ICSHeight::default()) + .query_connection(self.dst_connection_id()) .map_err(|e| ConnectionError::QueryError(self.dst_chain().id(), e))?; // Check if a connection is expected to exist on destination chain @@ -494,7 +493,7 @@ impl Connection { pub fn build_conn_try(&self) -> Result, ConnectionError> { let src_connection = self .src_chain() - .query_connection(self.src_connection_id(), ICSHeight::default()) + .query_connection(self.src_connection_id()) .map_err(|e| ConnectionError::QueryError(self.src_chain().id(), e))?; // TODO - check that the src connection is consistent with the try options @@ -626,7 +625,7 @@ impl Connection { let src_connection = self .src_chain() - .query_connection(self.src_connection_id(), ICSHeight::default()) + .query_connection(self.src_connection_id()) .map_err(|e| ConnectionError::QueryError(self.src_chain().id(), e))?; // TODO - check that the src connection is consistent with the ack options @@ -724,9 +723,10 @@ impl Connection { .src_chain() .query_latest_height() .map_err(|e| ConnectionError::QueryError(self.src_chain().id(), e))?; + let _src_connection = self .src_chain() - .query_connection(self.src_connection_id(), query_height) + .query_connection(self.src_connection_id()) .map_err(|_| { ConnectionError::Failed(format!( "missing connection {} on source chain", diff --git a/relayer/src/error.rs b/relayer/src/error.rs index cef2d190f3..47bbaaf109 100644 --- a/relayer/src/error.rs +++ b/relayer/src/error.rs @@ -82,6 +82,9 @@ pub enum Kind { #[error("Failed to create client {0}")] CreateClient(String), + #[error("Connection not found: {0}")] + ConnNotFound(ConnectionId), + /// Common failures to all connection messages #[error("Failed to build conn open message {0}: {1}")] ConnOpen(ConnectionId, String), diff --git a/relayer/src/link.rs b/relayer/src/link.rs index 685451c7c1..bc5bf839f2 100644 --- a/relayer/src/link.rs +++ b/relayer/src/link.rs @@ -1635,7 +1635,7 @@ impl Link { } let a_connection_id = a_channel.connection_hops()[0].clone(); - let a_connection = a_chain.query_connection(&a_connection_id, Height::zero())?; + let a_connection = a_chain.query_connection(&a_connection_id)?; if !a_connection.state_matches(&ConnectionState::Open) { return Err(LinkError::Failed(format!( diff --git a/relayer/src/supervisor.rs b/relayer/src/supervisor.rs index 28f4017db2..c5da278122 100644 --- a/relayer/src/supervisor.rs +++ b/relayer/src/supervisor.rs @@ -231,18 +231,17 @@ impl Supervisor { } }; for connection_id in client_connections { - let connection_end = - match chain.query_connection(&connection_id, Height::zero()) { - Ok(connection_end) => connection_end, - Err(e) => { - error!( - "skipping workers for chain {} and connection {}. \ + let connection_end = match chain.query_connection(&connection_id) { + Ok(connection_end) => connection_end, + Err(e) => { + error!( + "skipping workers for chain {} and connection {}. \ reason: failed to query connection end: {}", - chain_id, connection_id, e - ); - continue; - } - }; + chain_id, connection_id, e + ); + continue; + } + }; if !connection_end.state_matches(&State::Open) { continue;