From a7ad50b7b0778705fb64ef9ad111e9fabb1279dd Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 14 Jun 2021 12:47:52 +0200 Subject: [PATCH] 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;