Skip to content

Commit

Permalink
ClientState implementation with DomainTypes (informalsystems#247)
Browse files Browse the repository at this point in the history
* ClientState implementation with DomainTypes

* abci_query introduced
  • Loading branch information
greg-szabo authored Sep 22, 2020
1 parent 5511ed7 commit 38a0e1c
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 8 deletions.
1 change: 1 addition & 0 deletions relayer-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ authors = [
relayer = { path = "../relayer" }
ibc = { path = "../modules" }
tendermint = "0.15.0"
tendermint-proto = "0.1.0"

abscissa_tokio = "0.5.1"
anomaly = "0.2.0"
Expand Down
27 changes: 20 additions & 7 deletions relayer-cli/src/commands/query/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ use crate::prelude::*;
use abscissa_core::{Command, Options, Runnable};
use relayer::config::{ChainConfig, Config};

use crate::error::{Error, Kind};
use ibc::ics02_client::client_def::{AnyClientState, AnyConsensusState};
use ibc::ics24_host::error::ValidationError;
use ibc::ics24_host::identifier::{ClientId, ConnectionId};
use ibc::ics24_host::Path::{ClientConnections, ClientConsensusState, ClientState};
use relayer::chain::Chain;
use relayer::chain::CosmosSDKChain;
use tendermint::chain::Id as ChainId;
use tendermint_proto::DomainType;

/// Query client state command
#[derive(Clone, Command, Debug, Options)]
Expand Down Expand Up @@ -77,8 +79,13 @@ impl Runnable for QueryClientStateCmd {
status_info!("Options", "{:?}", opts);

let chain = CosmosSDKChain::from_config(chain_config).unwrap();
let res =
chain.query::<AnyClientState>(ClientState(opts.client_id), opts.height, opts.proof);

let res: Result<AnyClientState, Error> = chain
.abci_query(ClientState(opts.client_id), opts.height, opts.proof)
.map_err(|e| Kind::Query.context(e).into())
.and_then(|v| {
AnyClientState::decode_vec(&v).map_err(|e| Kind::Query.context(e).into())
});
match res {
Ok(cs) => status_info!("client state query result: ", "{:?}", cs),
Err(e) => status_info!("client state query error: ", "{:?}", e),
Expand Down Expand Up @@ -162,11 +169,17 @@ impl Runnable for QueryClientConsensusCmd {
status_info!("Options", "{:?}", opts);

let chain = CosmosSDKChain::from_config(chain_config).unwrap();
let res = chain.query::<AnyConsensusState>(
ClientConsensusState(opts.client_id, opts.consensus_height),
opts.height,
opts.proof,
);
let res: Result<AnyConsensusState, Error> = chain
.abci_query(
ClientConsensusState(opts.client_id, opts.consensus_height),
opts.height,
opts.proof,
)
.map_err(|e| Kind::Query.context(e).into())
.and_then(|v| {
AnyConsensusState::decode_vec(&v).map_err(|e| Kind::Query.context(e).into())
});

match res {
Ok(cs) => status_info!("client consensus state query result: ", "{:?}", cs),
Err(e) => status_info!("client consensus state query error: ", "{:?}", e),
Expand Down
4 changes: 4 additions & 0 deletions relayer-cli/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub enum Kind {
/// Input/output error
#[error("I/O error")]
Io,

/// Error during network query
#[error("query error")]
Query,
}

impl Kind {
Expand Down
1 change: 1 addition & 0 deletions relayer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ authors = [
ibc = { path = "../modules" }
tendermint = "0.15.0"
tendermint-rpc = { version = "0.15.0", features=["client"] }
tendermint-proto = "0.1.0"
anomaly = "0.2.0"
async-trait = "0.1.24"
humantime-serde = "1.0.0"
Expand Down
8 changes: 7 additions & 1 deletion relayer/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,17 @@ pub trait Chain {
// From the "Asynchronous Programming in Rust" book:
// Important extensions like `async fn` syntax in trait methods are still unimplemented
// https://rust-lang.github.io/async-book/01_getting_started/03_state_of_async_rust.html
// Todo: More generic chains might want to deal with domain types differently (no T).
// DEPRECATED: implement abci_query instead. Since this will be removed before the next release
// I'm commenting out the deprectaed warning. It would just confuse the clippy check in CI.
//#[deprecated(since = "0.0.4", note = "please use `abci_query` instead")]
fn query<T>(&self, data: Path, height: u64, prove: bool) -> Result<T, Self::Error>
where
T: TryFromRaw;

/// Perform a generic `query` using ABCI, and return the corresponding response data.
/// The naming is foreshadowing for an upcoming `grpc_query` function in the future.
fn abci_query(&self, data: Path, height: u64, prove: bool) -> Result<Vec<u8>, Self::Error>;

/// Returns the chain's identifier
fn id(&self) -> &ChainId {
&self.config().id
Expand Down
17 changes: 17 additions & 0 deletions relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ impl Chain for CosmosSDKChain {
.and_then(|r| T::try_from(r).map_err(|e| Kind::ResponseParsing.context(e).into()))
}

fn abci_query(&self, data: Path, height: u64, prove: bool) -> Result<Vec<u8>, Self::Error> {
let path = TendermintABCIPath::from_str(IBC_QUERY_PATH).unwrap();
if !data.is_provable() & prove {
return Err(Kind::Store
.context("requested proof for a path in the privateStore")
.into());
}
let response = block_on(abci_query(&self, path, data.to_string(), height, prove))?;

// Verify response proof, if requested.
if prove {
dbg!("Todo: implement proof verification."); // Todo: Verify proof
}

Ok(response)
}

fn config(&self) -> &ChainConfig {
&self.config
}
Expand Down

0 comments on commit 38a0e1c

Please sign in to comment.