Skip to content

Commit

Permalink
Include chain-id in hermes query clients output (informalsystems#995)
Browse files Browse the repository at this point in the history
* Added option to include chain ids. Client ids sorted by counter.

* Changelog

* Address comments

* Removed useless gumdrop derive attributes.

* Better info log message

* Better names for output struct. Using ChainId instead of String.

* Lowered log level to debug

* Succint help messages.

* Moved ClientId::suffix() into cosmos.rs
  • Loading branch information
adizere authored Jun 1, 2021
1 parent 8fc9c43 commit c9d2c43
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Started `unwrap` cleanup ([#871])

- [ibc-relayer-cli]
- Include chain-id in `query clients` command, and sort output by client counter ([#992])
- Improve config loading message ([#996])
- Improve Hermes worker spawn time for `start` command ([#998])
- Better Hermes help message when command is unrecognized ([#1003])
Expand All @@ -37,6 +38,7 @@
[#972]: https://github.com/informalsystems/ibc-rs/issues/972
[#975]: https://github.com/informalsystems/ibc-rs/issues/975
[#983]: https://github.com/informalsystems/ibc-rs/issues/983
[#992]: https://github.com/informalsystems/ibc-rs/issues/992
[#996]: https://github.com/informalsystems/ibc-rs/issues/996
[#998]: https://github.com/informalsystems/ibc-rs/issues/998
[#1003]: https://github.com/informalsystems/ibc-rs/issues/1003
Expand Down
2 changes: 1 addition & 1 deletion relayer-cli/src/commands/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub enum QueryCmd {
#[options(help = "Query information about clients")]
Client(QueryClientCmds),

#[options(help = "Query clients")]
#[options(help = "Query the identifiers of all clients on a chain")]
Clients(clients::QueryAllClientsCmd),

/// The `query connection` subcommand
Expand Down
66 changes: 62 additions & 4 deletions relayer-cli/src/commands/query/clients.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::sync::Arc;

use abscissa_core::{Command, Options, Runnable};
use serde::Serialize;
use tokio::runtime::Runtime as TokioRuntime;

use ibc::ics02_client::client_state::ClientState;
use ibc::ics24_host::identifier::{ChainId, ClientId};
use ibc_proto::ibc::core::client::v1::QueryClientStatesRequest;
use ibc_relayer::chain::{Chain, CosmosSdkChain};
Expand All @@ -14,7 +16,25 @@ use crate::prelude::*;
/// Query clients command
#[derive(Clone, Command, Debug, Options)]
pub struct QueryAllClientsCmd {
#[options(free, help = "identifier of the chain to query")]
#[options(free, required, help = "identifier of the chain to query")]
chain_id: ChainId,

#[options(
help = "filter for clients which target a specific chain id (implies '-o')",
meta = "ID"
)]
src_chain_id: Option<ChainId>,

#[options(
help = "omit printing the source chain for each client",
default = "false"
)]
omit_chain_ids: bool,
}

#[derive(Debug, Serialize)]
struct ClientChain {
client_id: ClientId,
chain_id: ChainId,
}

Expand Down Expand Up @@ -50,9 +70,47 @@ impl Runnable for QueryAllClientsCmd {

match res {
Ok(clients) => {
let client_ids: Vec<ClientId> =
clients.into_iter().map(|cs| cs.client_id).collect();
Output::success(client_ids).exit()
match self.src_chain_id.clone() {
None => {
match self.omit_chain_ids {
true => {
// Omit chain identifiers
debug!(
"printing identifiers of all clients hosted on chain {}",
self.chain_id
);
let out: Vec<ClientId> =
clients.into_iter().map(|cs| cs.client_id).collect();
Output::success(out).exit()
}
false => {
// Include chain identifiers
debug!("printing identifiers (and target chain identifiers) of all clients hosted on chain {}", self.chain_id);
let out: Vec<ClientChain> = clients
.into_iter()
.map(|cs| ClientChain {
client_id: cs.client_id,
chain_id: cs.client_state.chain_id(),
})
.collect();
Output::success(out).exit()
}
};
}
Some(source_chain_id) => {
debug!(
"printing identifiers of all clients hosted on chain {} which target chain {}",
self.chain_id, source_chain_id
);
// Filter and omit chain ids
let out: Vec<ClientId> = clients
.into_iter()
.filter(|cs| cs.client_state.chain_id().eq(&source_chain_id))
.map(|cs| cs.client_id)
.collect();
Output::success(out).exit()
}
}
}
Err(e) => Output::error(format!("{}", e)).exit(),
}
Expand Down
22 changes: 21 additions & 1 deletion relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,12 +503,20 @@ impl Chain for CosmosSdkChain {
.map_err(|e| Kind::Grpc.context(e))?
.into_inner();

let clients = response
// Deserialize into domain type
let mut clients: Vec<IdentifiedAnyClientState> = response
.client_states
.into_iter()
.filter_map(|cs| IdentifiedAnyClientState::try_from(cs).ok())
.collect();

// Sort by client identifier counter
clients.sort_by(|a, b| {
client_id_suffix(&a.client_id)
.unwrap_or(0) // Fallback to `0` suffix (no sorting) if client id is malformed
.cmp(&client_id_suffix(&b.client_id).unwrap_or(0))
});

Ok(clients)
}

Expand Down Expand Up @@ -1525,3 +1533,15 @@ fn encode_to_bech32(address: &str, account_prefix: &str) -> Result<String, Error

Ok(encoded)
}

/// Returns the suffix counter for a CosmosSDK client id.
/// Returns `None` if the client identifier is malformed
/// and the suffix could not be parsed.
pub fn client_id_suffix(client_id: &ClientId) -> Option<u64> {
client_id
.as_str()
.split('-')
.last()
.map(|e| e.parse::<u64>().ok())
.flatten()
}

0 comments on commit c9d2c43

Please sign in to comment.