From adad62a94c6db18a0c1cb743ced18c5885d3d64e Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 24 Jul 2020 18:45:28 -0400 Subject: [PATCH 1/9] Started to implement logic to query client connections #151 --- modules/src/path.rs | 16 ++++ modules/src/path/cosmos.rs | 5 ++ modules/src/path/ics.rs | 6 +- relayer/cli/src/commands/query.rs | 4 + relayer/cli/src/commands/query/client.rs | 105 ++++++++++++++++++++++- 5 files changed, 134 insertions(+), 2 deletions(-) diff --git a/modules/src/path.rs b/modules/src/path.rs index ca9059de76..3a478e978d 100644 --- a/modules/src/path.rs +++ b/modules/src/path.rs @@ -88,6 +88,22 @@ impl Path for ClientStatePath { } } +pub struct ClientConnectionsPath { + pub client_id: ClientId, +} + +impl ClientConnectionsPath { + pub fn new(client_id: ClientId) -> Self { + Self { client_id } + } +} + +impl Path for ClientConnectionsPath { + fn to_string(&self) -> String { + paths::client_connections_path(&self) + } +} + pub struct ChannelPath { pub port_id: PortId, channel_id: ChannelId, diff --git a/modules/src/path/cosmos.rs b/modules/src/path/cosmos.rs index 618b90204a..1bd97b094a 100644 --- a/modules/src/path/cosmos.rs +++ b/modules/src/path/cosmos.rs @@ -1,4 +1,5 @@ use super::{ChannelPath, ClientStatePath, ConnectionPath, ConsensusStatePath}; +use crate::path::ClientConnectionsPath; pub fn connection_path(path: &ConnectionPath) -> String { format!("connection/{}", path.connection_id) @@ -12,6 +13,10 @@ pub fn client_state_path(path: &ClientStatePath) -> String { format!("clientState/{}", path.client_id) } +pub fn client_connections_path(path: &ClientConnectionsPath) -> String { + format!("clients/{}/connections", path.client_id) +} + pub fn channel_path(path: &ChannelPath) -> String { format!("ports/{}/channels/{}", path.port_id, path.channel_id) } diff --git a/modules/src/path/ics.rs b/modules/src/path/ics.rs index 624a8e24ed..34f18a039e 100644 --- a/modules/src/path/ics.rs +++ b/modules/src/path/ics.rs @@ -1,4 +1,4 @@ -use super::{ChannelPath, ClientStatePath, ConnectionPath, ConsensusStatePath}; +use super::{ChannelPath, ClientStatePath, ConnectionPath, ConsensusStatePath, ClientConnectionsPath}; pub fn consensus_state_path(path: &ConsensusStatePath) -> String { format!("clients/{}/consensusState/{}", path.client_id, path.height) @@ -8,6 +8,10 @@ pub fn client_state_path(path: &ClientStatePath) -> String { format!("clients/{}/clientState", path.client_id) } +pub fn client_connections_path(path: &ClientConnectionsPath) -> String { + format!("clients/{}/connections", path.client_id) +} + pub fn connection_path(path: &ConnectionPath) -> String { format!("connections/{}", path.connection_id) } diff --git a/relayer/cli/src/commands/query.rs b/relayer/cli/src/commands/query.rs index e601c60bdb..4e236bb9e6 100644 --- a/relayer/cli/src/commands/query.rs +++ b/relayer/cli/src/commands/query.rs @@ -32,6 +32,10 @@ pub enum QueryClientCmds { /// The `query client consensus` subcommand #[options(help = "query client consensus")] Consensus(client::QueryClientConsensusCmd), + + /// The `query client connections` subcommand + #[options(help = "query client connections")] + Connections(client::QueryClientConnectionsCmd), } #[derive(Command, Debug, Options, Runnable)] diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index 64d866d285..a4afe93ff6 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -8,10 +8,20 @@ use relayer::config::{ChainConfig, Config}; //use relayer_modules::ics02_client::query::QueryClientFullState; use relayer_modules::ics24_host::identifier::ClientId; -//use crate::commands::utils::block_on; +use crate::commands::utils::block_on; use relayer::chain::tendermint::TendermintChain; +use relayer::query::{query, Request}; +use relayer_modules::error::Error; use relayer_modules::ics24_host::error::ValidationError; +use relayer_modules::path::{ClientConnectionsPath, Path}; +use std::str::FromStr; +use tendermint::abci::Path as TendermintPath; use tendermint::chain::Id as ChainId; +use relayer_modules::ics03_connection::connection::ConnectionEnd; + +// ***************************************************************** +// Query client state +// ***************************************************************** #[derive(Clone, Command, Debug, Options)] pub struct QueryClientStateCmd { @@ -95,6 +105,10 @@ impl Runnable for QueryClientStateCmd { } } +// ***************************************************************** +// Query client consensus +// ***************************************************************** + #[derive(Clone, Command, Debug, Options)] pub struct QueryClientConsensusCmd { #[options(free, help = "identifier of the chain to query")] @@ -214,6 +228,95 @@ fn validate_common_options( Ok((chain_config.clone(), client_id)) } +// ***************************************************************** +// Query client connections +// ***************************************************************** + +#[derive(Clone, Command, Debug, Options)] +pub struct QueryClientConnectionsCmd { + #[options(free, help = "identifier of the chain to query")] + chain_id: Option, + + #[options(free, help = "identifier of the client to query")] + client_id: Option, + + #[options(help = "height of the state to query", short = "h")] + height: Option, + + #[options(help = "whether proof is required", short = "p")] + proof: Option, +} + +#[derive(Debug)] +struct QueryClientConnectionsOptions { + client_id: ClientId, + height: u64, + proof: bool, +} + +impl Into for QueryClientConnectionsOptions { + fn into(self) -> Request { + Request { + path: Some(TendermintPath::from_str(&"store/ibc/key").unwrap()), + data: ClientConnectionsPath::new(self.client_id).to_string(), + height: self.height, + prove: self.proof, + } + } +} + +impl QueryClientConnectionsCmd { + fn validate_options( + &self, + config: &Config, + ) -> Result<(ChainConfig, QueryClientConnectionsOptions), String> { + let (chain_config, client_id) = + validate_common_options(&self.chain_id, &self.client_id, config)?; + + let opts = QueryClientConnectionsOptions { + client_id, + height: match self.height { + Some(h) => h, + None => 0 as u64, + }, + proof: match self.proof { + Some(proof) => proof, + None => true, + }, + }; + Ok((chain_config, opts)) + } +} + +impl Runnable for QueryClientConnectionsCmd { + fn run(&self) { + let config = app_config(); + + let (chain_config, opts) = match self.validate_options(&config) { + Err(err) => { + status_err!("invalid options: {}", err); + return; + } + Ok(result) => result, + }; + status_info!("Options", "{:?}", opts); + + // run without proof: + // cargo run --bin relayer -- -c relayer/relay/tests/config/fixtures/simple_config.toml query client connections ibc-test ethbridge --height 3 -p false + let chain = TendermintChain::from_config(chain_config).unwrap(); + let res: Result = block_on(query(&chain, opts)); + + match res { + Ok(cs) => status_info!("query client connections result: ", "{:?}", cs), + Err(e) => status_info!("query client connections error", "{}", e), + } + } +} + +// ***************************************************************** +// Tests +// ***************************************************************** + #[cfg(test)] mod tests { use crate::commands::query::client::QueryClientStateCmd; From cbefe399ecec5eaa46e4e8e4b9cd6c2508a05817 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Sat, 25 Jul 2020 18:05:05 -0400 Subject: [PATCH 2/9] Implemented a way to parse the client connections query response as a vector of string #151 --- modules/src/ics02_client/query.rs | 24 ++++++++++++++++++++++++ modules/src/path/ics.rs | 4 +++- relayer/cli/src/commands/query/client.rs | 3 +-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/modules/src/ics02_client/query.rs b/modules/src/ics02_client/query.rs index 4c4d5e7f10..6e52f19131 100644 --- a/modules/src/ics02_client/query.rs +++ b/modules/src/ics02_client/query.rs @@ -3,10 +3,34 @@ use std::marker::PhantomData; use crate::ics23_commitment::{CommitmentPath, CommitmentProof}; //use crate::ics02_client::state::{ClientState, ConsensusState}; +use crate::ics03_connection::error::Kind; use crate::ics24_host::identifier::ClientId; use crate::path::{ClientStatePath, ConsensusStatePath}; +use crate::try_from_raw::TryFromRaw; use crate::Height; +//TODO: This might need to be migrated to ibc-proto crate. But ClientConnections (as array of strings) +// might not be part of an official proto file +#[derive(::prost::Message)] +pub struct RawClientConnections { + #[prost(string, repeated, tag = "1")] + pub connections: ::std::vec::Vec, +} + +impl TryFromRaw for Vec { + type RawType = RawClientConnections; + type Error = anomaly::Error; + fn try_from(value: RawClientConnections) -> Result { + let mut client_connections: Vec = vec![]; + for conn in value.connections { + client_connections.push(conn); + } + Ok(client_connections) + // If no connections return error + //Err(Kind::MissingCounterparty.into()), + } +} + pub struct QueryClientFullState { pub chain_height: Height, pub client_id: ClientId, diff --git a/modules/src/path/ics.rs b/modules/src/path/ics.rs index 34f18a039e..4778eacf25 100644 --- a/modules/src/path/ics.rs +++ b/modules/src/path/ics.rs @@ -1,4 +1,6 @@ -use super::{ChannelPath, ClientStatePath, ConnectionPath, ConsensusStatePath, ClientConnectionsPath}; +use super::{ + ChannelPath, ClientConnectionsPath, ClientStatePath, ConnectionPath, ConsensusStatePath, +}; pub fn consensus_state_path(path: &ConsensusStatePath) -> String { format!("clients/{}/consensusState/{}", path.client_id, path.height) diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index a4afe93ff6..c96600d160 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -17,7 +17,6 @@ use relayer_modules::path::{ClientConnectionsPath, Path}; use std::str::FromStr; use tendermint::abci::Path as TendermintPath; use tendermint::chain::Id as ChainId; -use relayer_modules::ics03_connection::connection::ConnectionEnd; // ***************************************************************** // Query client state @@ -304,7 +303,7 @@ impl Runnable for QueryClientConnectionsCmd { // run without proof: // cargo run --bin relayer -- -c relayer/relay/tests/config/fixtures/simple_config.toml query client connections ibc-test ethbridge --height 3 -p false let chain = TendermintChain::from_config(chain_config).unwrap(); - let res: Result = block_on(query(&chain, opts)); + let res: Result, Error> = block_on(query(&chain, opts)); match res { Ok(cs) => status_info!("query client connections result: ", "{:?}", cs), From b607c1d424aa8a39054984e9c2b4f23d152771a7 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 27 Jul 2020 11:55:15 -0400 Subject: [PATCH 3/9] Added test for client connections query params #151 --- relayer/cli/src/commands/query/client.rs | 88 +++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index c96600d160..eb2a55dc7d 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -318,7 +318,7 @@ impl Runnable for QueryClientConnectionsCmd { #[cfg(test)] mod tests { - use crate::commands::query::client::QueryClientStateCmd; + use crate::commands::query::client::{QueryClientConnectionsCmd, QueryClientStateCmd}; use relayer::config::parse; #[test] @@ -406,4 +406,90 @@ mod tests { } } } + + #[test] + fn parse_query_client_connections_parameters() { + let default_params = QueryClientConnectionsCmd { + chain_id: Some("ibc0".to_string().parse().unwrap()), + client_id: Some("clientidone".to_string().parse().unwrap()), + height: Some(4), + proof: Some(false), + }; + + struct Test { + name: String, + params: QueryClientConnectionsCmd, + want_pass: bool, + } + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + params: default_params.clone(), + want_pass: true, + }, + Test { + name: "No chain specified".to_string(), + params: QueryClientConnectionsCmd { + chain_id: None, + ..default_params.clone() + }, + want_pass: false, + }, + Test { + name: "Chain not configured".to_string(), + params: QueryClientConnectionsCmd { + chain_id: Some("notibc0oribc1".to_string().parse().unwrap()), + ..default_params.clone() + }, + want_pass: false, + }, + Test { + name: "No client id specified".to_string(), + params: QueryClientConnectionsCmd { + client_id: None, + ..default_params.clone() + }, + want_pass: false, + }, + Test { + name: "Bad client id, non-alpha".to_string(), + params: QueryClientConnectionsCmd { + client_id: Some("p34".to_string()), + ..default_params.clone() + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + let path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/fixtures/two_chains.toml" + ); + + let config = parse(path).unwrap(); + + for test in tests { + let res = test.params.validate_options(&config); + + match res { + Ok(_res) => { + assert!( + test.want_pass, + "validate_options should have failed for test {}", + test.name + ); + } + Err(err) => { + assert!( + !test.want_pass, + "validate_options failed for test {}, \nerr {}", + test.name, err + ); + } + } + } + } } From 4c5523f21c6f228df2fc1a06635a5a144f3f8723 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 28 Jul 2020 14:42:55 -0400 Subject: [PATCH 4/9] Refactored TryFromRaw for Vec as suggested on review #169 --- modules/src/ics02_client/query.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/src/ics02_client/query.rs b/modules/src/ics02_client/query.rs index 6e52f19131..b5a653bbd1 100644 --- a/modules/src/ics02_client/query.rs +++ b/modules/src/ics02_client/query.rs @@ -21,13 +21,11 @@ impl TryFromRaw for Vec { type RawType = RawClientConnections; type Error = anomaly::Error; fn try_from(value: RawClientConnections) -> Result { - let mut client_connections: Vec = vec![]; - for conn in value.connections { - client_connections.push(conn); + if !value.connections.is_empty() { + Ok(value.connections) + } else { + Err(Kind::ConnectionNotFound.into()) } - Ok(client_connections) - // If no connections return error - //Err(Kind::MissingCounterparty.into()), } } From b4dfcf3cd8466ed4652a6ca9af88e200de3e2533 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 28 Jul 2020 14:57:13 -0400 Subject: [PATCH 5/9] Fixed comments and fixed command line example to test the query client connections #169 --- relayer/cli/src/commands/query/client.rs | 25 +++++------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index eb2a55dc7d..ba5eb3ba7b 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -2,10 +2,7 @@ use crate::prelude::*; use abscissa_core::{Command, Options, Runnable}; use relayer::config::{ChainConfig, Config}; -//use relayer::query::client::{query_client_consensus_state, query_client_full_state}; -//use relayer::query::{query, Request}; -//use relayer_modules::ics02_client::query::QueryClientFullState; use relayer_modules::ics24_host::identifier::ClientId; use crate::commands::utils::block_on; @@ -18,10 +15,7 @@ use std::str::FromStr; use tendermint::abci::Path as TendermintPath; use tendermint::chain::Id as ChainId; -// ***************************************************************** -// Query client state -// ***************************************************************** - +/// Query client state command #[derive(Clone, Command, Debug, Options)] pub struct QueryClientStateCmd { #[options(free, help = "identifier of the chain to query")] @@ -104,10 +98,7 @@ impl Runnable for QueryClientStateCmd { } } -// ***************************************************************** -// Query client consensus -// ***************************************************************** - +/// Query client consensus command #[derive(Clone, Command, Debug, Options)] pub struct QueryClientConsensusCmd { #[options(free, help = "identifier of the chain to query")] @@ -227,10 +218,7 @@ fn validate_common_options( Ok((chain_config.clone(), client_id)) } -// ***************************************************************** -// Query client connections -// ***************************************************************** - +/// Query client connections command #[derive(Clone, Command, Debug, Options)] pub struct QueryClientConnectionsCmd { #[options(free, help = "identifier of the chain to query")] @@ -301,7 +289,7 @@ impl Runnable for QueryClientConnectionsCmd { status_info!("Options", "{:?}", opts); // run without proof: - // cargo run --bin relayer -- -c relayer/relay/tests/config/fixtures/simple_config.toml query client connections ibc-test ethbridge --height 3 -p false + // cargo run --bin relayer -- -c relayer/relay/tests/config/fixtures/relayer_conf_example.toml query client connections chain_A clientidone -h 4 -p false let chain = TendermintChain::from_config(chain_config).unwrap(); let res: Result, Error> = block_on(query(&chain, opts)); @@ -312,10 +300,7 @@ impl Runnable for QueryClientConnectionsCmd { } } -// ***************************************************************** -// Tests -// ***************************************************************** - +/// Tests #[cfg(test)] mod tests { use crate::commands::query::client::{QueryClientConnectionsCmd, QueryClientStateCmd}; From 2c4771be2d54d7f57783fddb4953452f195dd24d Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 28 Jul 2020 15:32:40 -0400 Subject: [PATCH 6/9] Removing unused references #169 --- modules/src/ics02_client/query.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/src/ics02_client/query.rs b/modules/src/ics02_client/query.rs index b5a653bbd1..81a04dc3b0 100644 --- a/modules/src/ics02_client/query.rs +++ b/modules/src/ics02_client/query.rs @@ -1,8 +1,6 @@ use std::marker::PhantomData; use crate::ics23_commitment::{CommitmentPath, CommitmentProof}; - -//use crate::ics02_client::state::{ClientState, ConsensusState}; use crate::ics03_connection::error::Kind; use crate::ics24_host::identifier::ClientId; use crate::path::{ClientStatePath, ConsensusStatePath}; From 678439aaaaab008c1bd4aed46ad3da17dbe46aff Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 29 Jul 2020 12:01:28 -0400 Subject: [PATCH 7/9] Update relayer/cli/src/commands/query/client.rs Thanks for fixing Co-authored-by: Greg Szabo <16846635+greg-szabo@users.noreply.github.com> --- relayer/cli/src/commands/query/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index c20ef4783a..67906a4ee3 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use abscissa_core::{Command, Options, Runnable}; use relayer::config::{ChainConfig, Config}; -use relayer::chain::tendermint::TendermintChain; +use relayer::chain::CosmosSDKChain; use relayer::chain::Chain; use relayer_modules::ics24_host::error::ValidationError; use relayer_modules::ics24_host::identifier::ClientId; From 7cc05e57a57abb3f89bfd8136f821d8233a05a5b Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 29 Jul 2020 12:01:42 -0400 Subject: [PATCH 8/9] Update relayer/cli/src/commands/query/client.rs Thanks for fixing Co-authored-by: Greg Szabo <16846635+greg-szabo@users.noreply.github.com> --- relayer/cli/src/commands/query/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index 67906a4ee3..3feab87e72 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -288,7 +288,7 @@ impl Runnable for QueryClientConnectionsCmd { }; status_info!("Options", "{:?}", opts); - let chain = TendermintChain::from_config(chain_config).unwrap(); + let chain = CosmosSDKChain::from_config(chain_config).unwrap(); let res = chain.query::>(ClientConnections(opts.client_id), opts.height, opts.proof); match res { From 3d3a2e021826fc4e22c60727c8c3d30b49d64ffb Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 29 Jul 2020 12:05:17 -0400 Subject: [PATCH 9/9] Fixing cargo fmt error #169 --- relayer/cli/src/commands/query/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/cli/src/commands/query/client.rs b/relayer/cli/src/commands/query/client.rs index 3feab87e72..7e25766c0b 100644 --- a/relayer/cli/src/commands/query/client.rs +++ b/relayer/cli/src/commands/query/client.rs @@ -3,8 +3,8 @@ use crate::prelude::*; use abscissa_core::{Command, Options, Runnable}; use relayer::config::{ChainConfig, Config}; -use relayer::chain::CosmosSDKChain; use relayer::chain::Chain; +use relayer::chain::CosmosSDKChain; use relayer_modules::ics24_host::error::ValidationError; use relayer_modules::ics24_host::identifier::ClientId; use relayer_modules::ics24_host::Path::ClientConnections;