From 30f67571d1bfc8a69966d69a73a8a72f768f98cc Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Fri, 4 Jun 2021 15:06:52 +0200 Subject: [PATCH 1/4] Use GRPC to query connection end --- relayer-cli/src/commands/create/channel.rs | 2 +- relayer-cli/src/commands/query/connection.rs | 6 +-- relayer-cli/src/commands/tx/channel.rs | 6 +-- relayer-cli/src/commands/tx/transfer.rs | 2 +- relayer/src/chain.rs | 6 +-- relayer/src/chain/cosmos.rs | 54 ++++++++++++++++---- relayer/src/chain/counterparty.rs | 2 +- relayer/src/chain/handle.rs | 7 +-- relayer/src/chain/handle/prod.rs | 7 +-- relayer/src/chain/mock.rs | 6 +-- relayer/src/chain/runtime.rs | 7 ++- relayer/src/channel.rs | 12 ++--- relayer/src/connection.rs | 14 ++--- relayer/src/error.rs | 3 ++ relayer/src/link.rs | 2 +- relayer/src/supervisor.rs | 21 ++++---- 16 files changed, 83 insertions(+), 74 deletions(-) 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 fe89cc64ba..fcb68ee767 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 1636c9dce0..60d45e2800 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}; @@ -315,6 +316,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 { @@ -746,16 +788,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 e1a0c7b573..c70ed6f832 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 02c429bd0f..ddf8f7c572 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 96078d5fb0..d785ec2097 100644 --- a/relayer/src/chain/mock.rs +++ b/relayer/src/chain/mock.rs @@ -160,11 +160,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 73376cdf93..141fe49470 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 }) => { @@ -606,10 +606,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 75bff12ad9..758b25adf5 100644 --- a/relayer/src/channel.rs +++ b/relayer/src/channel.rs @@ -190,7 +190,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 @@ -238,7 +238,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() @@ -742,7 +742,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 @@ -845,7 +845,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 @@ -936,7 +936,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 @@ -1078,7 +1078,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; From a7ad50b7b0778705fb64ef9ad111e9fabb1279dd Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 14 Jun 2021 12:47:52 +0200 Subject: [PATCH 2/4] Add back height parameter --- relayer-cli/src/commands/create/channel.rs | 3 +- relayer-cli/src/commands/query/connection.rs | 7 +- relayer-cli/src/commands/tx/channel.rs | 6 +- relayer-cli/src/commands/tx/transfer.rs | 2 +- relayer/src/chain.rs | 6 +- relayer/src/chain/cosmos.rs | 100 +++++++++++-------- relayer/src/chain/counterparty.rs | 2 +- relayer/src/chain/handle.rs | 7 +- relayer/src/chain/handle/prod.rs | 7 +- relayer/src/chain/mock.rs | 7 +- relayer/src/chain/runtime.rs | 7 +- relayer/src/channel.rs | 12 +-- relayer/src/connection.rs | 12 +-- relayer/src/link.rs | 2 +- relayer/src/supervisor.rs | 21 ++-- 15 files changed, 122 insertions(+), 79 deletions(-) diff --git a/relayer-cli/src/commands/create/channel.rs b/relayer-cli/src/commands/create/channel.rs index c4973ded8b..1c8c135124 100644 --- a/relayer-cli/src/commands/create/channel.rs +++ b/relayer-cli/src/commands/create/channel.rs @@ -131,9 +131,8 @@ 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) + .query_connection(connection_a_id, height) .unwrap_or_else(exit_with_unrecoverable_error); - // Query the client state, obtain the identifier of chain b. let chain_b_id = chain_a .query_client_state(conn_end.client_id(), height) diff --git a/relayer-cli/src/commands/query/connection.rs b/relayer-cli/src/commands/query/connection.rs index eaea761a92..dd62d2755a 100644 --- a/relayer-cli/src/commands/query/connection.rs +++ b/relayer-cli/src/commands/query/connection.rs @@ -22,6 +22,9 @@ 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 @@ -45,7 +48,9 @@ impl Runnable for QueryConnectionEndCmd { let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); - let res = chain.query_connection(&self.connection_id); + let height = ibc::Height::new(chain.id().version(), self.height.unwrap_or(0_u64)); + let res = chain.query_connection(&self.connection_id, height); + 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 a720c0abf1..4f35ded806 100644 --- a/relayer-cli/src/commands/tx/channel.rs +++ b/relayer-cli/src/commands/tx/channel.rs @@ -1,6 +1,7 @@ use abscissa_core::{Command, Options, Runnable}; use ibc::events::IbcEvent; +use ibc::ics02_client::height::Height; use ibc::ics03_connection::connection::ConnectionEnd; use ibc::ics04_channel::channel::Order; use ibc::ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}; @@ -22,7 +23,10 @@ macro_rules! tx_chan_cmd { }; // Retrieve the connection - let dst_connection = match chains.dst.query_connection(&$self.dst_conn_id) { + let dst_connection = match chains + .dst + .query_connection(&$self.dst_conn_id, Height::zero()) + { 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 d8c8ac24dc..65569dc175 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) + .query_connection(conn_id, Height::zero()) .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 fcb68ee767..fe89cc64ba 100644 --- a/relayer/src/chain.rs +++ b/relayer/src/chain.rs @@ -168,7 +168,11 @@ pub trait Chain: Sized { request: QueryClientConnectionsRequest, ) -> Result, Error>; - fn query_connection(&self, connection_id: &ConnectionId) -> Result; + fn query_connection( + &self, + connection_id: &ConnectionId, + height: ICSHeight, + ) -> 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 60d45e2800..e4cffbe72a 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -316,47 +316,6 @@ 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 { @@ -788,8 +747,63 @@ impl Chain for CosmosSdkChain { Ok(ids) } - fn query_connection(&self, connection_id: &ConnectionId) -> Result { - self.block_on(async { self.do_query_connection(connection_id).await }) + fn query_connection( + &self, + connection_id: &ConnectionId, + height: ICSHeight, + ) -> Result { + async fn do_query_connection( + chain: &CosmosSdkChain, + connection_id: &ConnectionId, + height: ICSHeight, + ) -> Result { + use ibc_proto::ibc::core::connection::v1 as connection; + use tonic::{metadata::MetadataValue, IntoRequest}; + + let mut client = + connection::query_client::QueryClient::connect(chain.grpc_addr.clone()) + .await + .map_err(|e| Kind::Grpc.context(e))?; + + let mut request = connection::QueryConnectionRequest { + connection_id: connection_id.to_string(), + } + .into_request(); + + let height_param = MetadataValue::from_str(&height.revision_height.to_string()) + .map_err(|e| Kind::Grpc.context(e))?; + + request + .metadata_mut() + .insert("x-cosmos-block-height", height_param); + + let response = client.connection(request).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()) + } + } + } + + self.block_on(async { do_query_connection(self, connection_id, height).await }) } fn query_connection_channels( diff --git a/relayer/src/chain/counterparty.rs b/relayer/src/chain/counterparty.rs index 6f0293e1fb..958bc9b2ff 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) + .query_connection(&connection_id, Height::zero()) .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 c70ed6f832..e1a0c7b573 100644 --- a/relayer/src/chain/handle.rs +++ b/relayer/src/chain/handle.rs @@ -202,6 +202,7 @@ pub enum ChainRequest { QueryConnection { connection_id: ConnectionId, + height: Height, reply_to: ReplyTo, }, @@ -354,7 +355,11 @@ pub trait ChainHandle: DynClone + Send + Sync + Debug { fn query_compatible_versions(&self) -> Result, Error>; - fn query_connection(&self, connection_id: &ConnectionId) -> Result; + fn query_connection( + &self, + connection_id: &ConnectionId, + height: Height, + ) -> Result; fn query_connection_channels( &self, diff --git a/relayer/src/chain/handle/prod.rs b/relayer/src/chain/handle/prod.rs index ddf8f7c572..02c429bd0f 100644 --- a/relayer/src/chain/handle/prod.rs +++ b/relayer/src/chain/handle/prod.rs @@ -178,9 +178,14 @@ impl ChainHandle for ProdChainHandle { self.send(|reply_to| ChainRequest::QueryCompatibleVersions { reply_to }) } - fn query_connection(&self, connection_id: &ConnectionId) -> Result { + fn query_connection( + &self, + connection_id: &ConnectionId, + height: Height, + ) -> 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 d785ec2097..c073b681ad 100644 --- a/relayer/src/chain/mock.rs +++ b/relayer/src/chain/mock.rs @@ -12,6 +12,7 @@ use ibc::downcast; use ibc::events::IbcEvent; use ibc::ics02_client::client_consensus::{AnyConsensusState, AnyConsensusStateWithHeight}; use ibc::ics02_client::client_state::{AnyClientState, IdentifiedAnyClientState}; +use ibc::ics02_client::height::Height as ICSHeight; use ibc::ics03_connection::connection::ConnectionEnd; use ibc::ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}; use ibc::ics04_channel::packet::{PacketMsgType, Sequence}; @@ -160,7 +161,11 @@ impl Chain for MockChain { unimplemented!() } - fn query_connection(&self, _connection_id: &ConnectionId) -> Result { + fn query_connection( + &self, + _connection_id: &ConnectionId, + _height: ICSHeight, + ) -> Result { unimplemented!() } diff --git a/relayer/src/chain/runtime.rs b/relayer/src/chain/runtime.rs index 141fe49470..73376cdf93 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, reply_to }) => { - self.query_connection(connection_id, reply_to)? + Ok(ChainRequest::QueryConnection { connection_id, height, reply_to }) => { + self.query_connection(connection_id, height, reply_to)? }, Ok(ChainRequest::QueryConnectionChannels { request, reply_to }) => { @@ -606,9 +606,10 @@ 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); + let connection_end = self.chain.query_connection(&connection_id, height); reply_to.send(connection_end).map_err(Kind::channel)?; diff --git a/relayer/src/channel.rs b/relayer/src/channel.rs index 758b25adf5..75bff12ad9 100644 --- a/relayer/src/channel.rs +++ b/relayer/src/channel.rs @@ -190,7 +190,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)?; + let connection = chain.query_connection(&connection_id, Height::zero())?; let connection_counterparty = connection.counterparty(); let counterparty_connection_id = connection_counterparty @@ -238,7 +238,7 @@ impl Channel { WorkerChannelError::MissingConnectionHops(channel.src_channel_id.clone(), chain.id()) })?; - let a_connection = chain.query_connection(&a_connection_id)?; + let a_connection = chain.query_connection(&a_connection_id, Height::zero())?; let b_connection_id = a_connection .counterparty() .connection_id() @@ -742,7 +742,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id()) + .query_connection(self.dst_connection_id(), Height::zero()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self @@ -845,7 +845,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id()) + .query_connection(self.dst_connection_id(), Height::zero()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self @@ -936,7 +936,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id()) + .query_connection(self.dst_connection_id(), Height::zero()) .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; let query_height = self @@ -1078,7 +1078,7 @@ impl Channel { // Connection must exist on destination self.dst_chain() - .query_connection(self.dst_connection_id()) + .query_connection(self.dst_connection_id(), Height::zero()) .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 260aaf0e62..9fa52fdc8b 100644 --- a/relayer/src/connection.rs +++ b/relayer/src/connection.rs @@ -289,11 +289,11 @@ impl Connection { counter += 1; // Continue loop if query error - let a_connection = a_chain.query_connection(&self.src_connection_id()); + let a_connection = a_chain.query_connection(&self.src_connection_id(), Height::zero()); if a_connection.is_err() { continue; } - let b_connection = b_chain.query_connection(&self.dst_connection_id()); + let b_connection = b_chain.query_connection(&self.dst_connection_id(), Height::zero()); if b_connection.is_err() { continue; } @@ -388,7 +388,7 @@ impl Connection { // Retrieve existing connection if any let dst_connection = self .dst_chain() - .query_connection(self.dst_connection_id()) + .query_connection(self.dst_connection_id(), Height::zero()) .map_err(|e| ConnectionError::QueryError(self.dst_chain().id(), e))?; // Check if a connection is expected to exist on destination chain @@ -493,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()) + .query_connection(self.src_connection_id(), Height::zero()) .map_err(|e| ConnectionError::QueryError(self.src_chain().id(), e))?; // TODO - check that the src connection is consistent with the try options @@ -625,7 +625,7 @@ impl Connection { let src_connection = self .src_chain() - .query_connection(self.src_connection_id()) + .query_connection(self.src_connection_id(), Height::zero()) .map_err(|e| ConnectionError::QueryError(self.src_chain().id(), e))?; // TODO - check that the src connection is consistent with the ack options @@ -726,7 +726,7 @@ impl Connection { let _src_connection = self .src_chain() - .query_connection(self.src_connection_id()) + .query_connection(self.src_connection_id(), query_height) .map_err(|_| { ConnectionError::Failed(format!( "missing connection {} on source chain", diff --git a/relayer/src/link.rs b/relayer/src/link.rs index bc5bf839f2..685451c7c1 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)?; + let a_connection = a_chain.query_connection(&a_connection_id, Height::zero())?; 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 c5da278122..28f4017db2 100644 --- a/relayer/src/supervisor.rs +++ b/relayer/src/supervisor.rs @@ -231,17 +231,18 @@ impl Supervisor { } }; for connection_id in client_connections { - let connection_end = match chain.query_connection(&connection_id) { - Ok(connection_end) => connection_end, - Err(e) => { - error!( - "skipping workers for chain {} and connection {}. \ + 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 {}. \ 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; From d1b41dd58a7dda9e3f8ae1b8aa3d267ea7887d75 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 14 Jun 2021 12:53:02 +0200 Subject: [PATCH 3/4] Remove unrelated changes --- relayer-cli/src/commands/create/channel.rs | 1 + relayer-cli/src/commands/query/connection.rs | 1 - relayer-cli/src/commands/tx/channel.rs | 4 ++-- relayer/src/chain/mock.rs | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/relayer-cli/src/commands/create/channel.rs b/relayer-cli/src/commands/create/channel.rs index 1c8c135124..fc5df65204 100644 --- a/relayer-cli/src/commands/create/channel.rs +++ b/relayer-cli/src/commands/create/channel.rs @@ -133,6 +133,7 @@ impl CreateChannelCommand { let conn_end = chain_a .query_connection(connection_a_id, height) .unwrap_or_else(exit_with_unrecoverable_error); + // Query the client state, obtain the identifier of chain b. let chain_b_id = chain_a .query_client_state(conn_end.client_id(), height) diff --git a/relayer-cli/src/commands/query/connection.rs b/relayer-cli/src/commands/query/connection.rs index dd62d2755a..e549fa2f62 100644 --- a/relayer-cli/src/commands/query/connection.rs +++ b/relayer-cli/src/commands/query/connection.rs @@ -50,7 +50,6 @@ impl Runnable for QueryConnectionEndCmd { let height = ibc::Height::new(chain.id().version(), self.height.unwrap_or(0_u64)); let res = chain.query_connection(&self.connection_id, height); - 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 4f35ded806..47476a45f6 100644 --- a/relayer-cli/src/commands/tx/channel.rs +++ b/relayer-cli/src/commands/tx/channel.rs @@ -1,10 +1,10 @@ use abscissa_core::{Command, Options, Runnable}; use ibc::events::IbcEvent; -use ibc::ics02_client::height::Height; 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; @@ -25,7 +25,7 @@ macro_rules! tx_chan_cmd { // Retrieve the connection let dst_connection = match chains .dst - .query_connection(&$self.dst_conn_id, Height::zero()) + .query_connection(&$self.dst_conn_id, Height::default()) { Ok(connection) => connection, Err(e) => return Output::error(format!("{}", e)).exit(), diff --git a/relayer/src/chain/mock.rs b/relayer/src/chain/mock.rs index c073b681ad..96078d5fb0 100644 --- a/relayer/src/chain/mock.rs +++ b/relayer/src/chain/mock.rs @@ -12,7 +12,6 @@ use ibc::downcast; use ibc::events::IbcEvent; use ibc::ics02_client::client_consensus::{AnyConsensusState, AnyConsensusStateWithHeight}; use ibc::ics02_client::client_state::{AnyClientState, IdentifiedAnyClientState}; -use ibc::ics02_client::height::Height as ICSHeight; use ibc::ics03_connection::connection::ConnectionEnd; use ibc::ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}; use ibc::ics04_channel::packet::{PacketMsgType, Sequence}; @@ -164,7 +163,7 @@ impl Chain for MockChain { fn query_connection( &self, _connection_id: &ConnectionId, - _height: ICSHeight, + _height: Height, ) -> Result { unimplemented!() } From 531832b8c4c2fac1def4fe4bbfcd767cfecfacf3 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 14 Jun 2021 13:52:28 +0200 Subject: [PATCH 4/4] Rename ConnNotFound to ConnectionNotFound --- relayer/src/chain/cosmos.rs | 4 ++-- relayer/src/error.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index e4cffbe72a..f5e0a9df91 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -779,7 +779,7 @@ impl Chain for CosmosSdkChain { let response = client.connection(request).await.map_err(|e| { if e.code() == Code::NotFound { - Kind::ConnNotFound(connection_id.clone()).into() + Kind::ConnectionNotFound(connection_id.clone()).into() } else { Kind::Grpc.context(e) } @@ -798,7 +798,7 @@ impl Chain for CosmosSdkChain { // 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()) + Err(Kind::ConnectionNotFound(connection_id.clone()).into()) } } } diff --git a/relayer/src/error.rs b/relayer/src/error.rs index 47bbaaf109..26c6103275 100644 --- a/relayer/src/error.rs +++ b/relayer/src/error.rs @@ -83,7 +83,7 @@ pub enum Kind { CreateClient(String), #[error("Connection not found: {0}")] - ConnNotFound(ConnectionId), + ConnectionNotFound(ConnectionId), /// Common failures to all connection messages #[error("Failed to build conn open message {0}: {1}")]