From efbb695a50c4c0e8122907b4bdb849b3d64586cb Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Tue, 17 Mar 2020 19:00:57 +0100 Subject: [PATCH 01/13] debugging the consensus query with proof --- relayer/cli/Cargo.toml | 4 + relayer/cli/src/commands.rs | 7 +- relayer/cli/src/commands/query.rs | 13 +++ relayer/cli/src/commands/query/query.rs | 96 +++++++++++++++++++ relayer/relay/src/query.rs | 2 +- .../relay/src/query/client_consensus_state.rs | 35 +++++-- 6 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 relayer/cli/src/commands/query.rs create mode 100644 relayer/cli/src/commands/query/query.rs diff --git a/relayer/cli/Cargo.toml b/relayer/cli/Cargo.toml index 7050e1d129..5de8dc95d1 100644 --- a/relayer/cli/Cargo.toml +++ b/relayer/cli/Cargo.toml @@ -9,6 +9,10 @@ authors = [ [dependencies] relayer = { path = "../relay" } +relayer-modules = { path = "../../modules" } + +tendermint = { git = "https://github.com/interchainio/tendermint-rs.git" } +tokio = "0.2" anomaly = "0.2.0" gumdrop = "0.7" diff --git a/relayer/cli/src/commands.rs b/relayer/cli/src/commands.rs index 03d7b9d9b4..2803145d14 100644 --- a/relayer/cli/src/commands.rs +++ b/relayer/cli/src/commands.rs @@ -8,8 +8,9 @@ mod config; mod start; mod version; +mod query; -use self::{config::ConfigCmd, start::StartCmd, version::VersionCmd}; +use self::{config::ConfigCmd, start::StartCmd, version::VersionCmd, query::QueryCmd}; use crate::config::Config; use abscissa_core::{Command, Configurable, FrameworkError, Help, Options, Runnable}; @@ -36,6 +37,10 @@ pub enum CliCmd { /// The `version` subcommand #[options(help = "display version information")] Version(VersionCmd), + + /// The `query` subcommand + #[options(help = "query state from chain")] + Query(QueryCmd), } /// This trait allows you to define how application configuration is loaded. diff --git a/relayer/cli/src/commands/query.rs b/relayer/cli/src/commands/query.rs new file mode 100644 index 0000000000..49502e5b8f --- /dev/null +++ b/relayer/cli/src/commands/query.rs @@ -0,0 +1,13 @@ +//! `query` subcommand + +use abscissa_core::{Command, Options, Runnable}; + +mod query; + +/// `query` subcommand +#[derive(Command, Debug, Options, Runnable)] +pub enum QueryCmd { + /// The `query clients` subcommand + #[options(help = "IBC query to a full node")] + Clients(query::QueryClientsCmd), +} diff --git a/relayer/cli/src/commands/query/query.rs b/relayer/cli/src/commands/query/query.rs new file mode 100644 index 0000000000..32cbda1947 --- /dev/null +++ b/relayer/cli/src/commands/query/query.rs @@ -0,0 +1,96 @@ +use crate::prelude::*; + +use abscissa_core::{Command, Options, Runnable}; +use tendermint::net; +use core::future::Future; +use tokio::runtime::Builder; +use relayer_modules::ics24_host::client::ClientId; + +#[derive(Command, Debug, Options)] +pub struct QueryClientsCmd { + #[options(free, help = "rpc address")] + // TODO replace this with the chain-id string and retrieve the rpc_addr from `Chain` + rpc_addr: Option, + proof: Option, +} + +#[derive(Debug)] +struct QueryOptions<'a> { + /// identifier of chain to initialize light client for + rpc_addr: &'a net::Address, + proof: bool, +} + +impl QueryClientsCmd { + fn validate_options(&self) -> Result, &'static str> { + let proof = match self.proof { + Some(proof) => proof, + None => true, + }; + + match &self.rpc_addr { + Some(rpc_addr) => Ok(QueryOptions { + rpc_addr, proof + }), + None => Err("missing rpc address"), + } + } +} + +use relayer::query::client_consensus_state::query_client_consensus_state; +use std::str::FromStr; +use relayer::chain::tendermint::TendermintChain; +use relayer::config::ChainConfig; +use tendermint::chain::Id as ChainId; + +impl Runnable for QueryClientsCmd { + fn run(&self) { + let opts = match self.validate_options() { + Err(err) => { + status_err!("invalid options: {}", err); + return; + } + Ok(opts) => opts, + }; + status_info!("Options", "{:?}", opts); + + // TODO remove soon and replace with proper sequence + // run without proof + // export RUST_BACKTRACE=1 ; cargo run query clients localhost:26657 -p false + // this causes earlier error in ibc_query() -> `.map_err(|e| error::Kind::Rpc.context(e))?;:` + // + // run with proof: + // export RUST_BACKTRACE=1 ; cargo run query clients localhost:26657 + // this one fails in amino_unmarshal_binary_length_prefixed() as expected + // + // To test this start a Gaia node and configure a client with the go relayer. + // Proper way is to query client state (not yet implemented), get the consensus_height from + // the response and then query the consensus state. In the absence of this, look at logs + // and check the height :( + let consensus_height = 17 as u64; + + // Also, the relayer should have been started with config, chain information parsed and + // the `Chain` already created. This also is not implemented therefore the weird sequence + // below. + let client_id = ClientId::from_str("ibconeclient").unwrap(); + let chain_id = ChainId::from_str("ibc0").unwrap(); + let chain_height = 0 as u64; + + let chain = TendermintChain::from_config(ChainConfig { + id: chain_id, rpc_addr: opts.rpc_addr.clone(), account_prefix: "".to_string(), key_name: "".to_string(), client_ids: vec![], gas: 0 }).unwrap(); + + let res = block_on( + query_client_consensus_state(&chain, chain_height, client_id, consensus_height, opts.proof)).unwrap(); + println!("abci response: {:?}", res.proof_height); + // end remove soon + } +} + +fn block_on(future: F) -> F::Output { + Builder::new() + .basic_scheduler() + .enable_all() + .build() + .unwrap() + .block_on(future) +} \ No newline at end of file diff --git a/relayer/relay/src/query.rs b/relayer/relay/src/query.rs index 14a930ad34..847b1498c2 100644 --- a/relayer/relay/src/query.rs +++ b/relayer/relay/src/query.rs @@ -59,5 +59,5 @@ where /// is_query_store_with_proofxpects a format like ///, /// where queryType must be "store" and subpath must be "key" to require a proof. fn is_query_store_with_proof(_path: &abci::Path) -> bool { - todo!() + false } diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index c2209a24b5..f45c4fd1aa 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -18,16 +18,18 @@ pub struct QueryClientConsensusState { pub client_id: ClientId, pub consensus_height: Height, pub consensus_state_path: ConsensusStatePath, + pub prove: bool, marker: PhantomData, } impl QueryClientConsensusState { - pub fn new(chain_height: Height, client_id: ClientId, consensus_height: Height) -> Self { + pub fn new(chain_height: Height, client_id: ClientId, consensus_height: Height, prove: bool) -> Self { Self { chain_height, client_id: client_id.clone(), consensus_height, consensus_state_path: ConsensusStatePath::new(client_id, consensus_height), + prove, marker: PhantomData, } } @@ -48,7 +50,7 @@ where } fn prove(&self) -> bool { - true + self.prove } fn data(&self) -> Vec { @@ -58,7 +60,7 @@ where pub struct ConsensusStateResponse { pub consensus_state: CS, - pub proof: CommitmentProof, + pub proof: Option, pub proof_path: CommitmentPath, pub proof_height: Height, } @@ -67,17 +69,23 @@ impl ConsensusStateResponse { pub fn new( client_id: ClientId, consensus_state: CS, - abci_proof: abci::Proof, + abci_proof: Option, proof_height: Height, ) -> Self { - let proof = CommitmentProof::from_bytes(abci_proof.as_ref()); + let mut proof: CommitmentProof = CommitmentProof; + match abci_proof { + Some(abci_proof) => { + proof = CommitmentProof::from_bytes(abci_proof.as_ref()); + } + None => {} + } let proof_path = CommitmentPath::from_path(ConsensusStatePath::new(client_id, proof_height)); ConsensusStateResponse { consensus_state, - proof, + proof: Option::from(proof), proof_path, proof_height, } @@ -99,7 +107,17 @@ where Ok(ConsensusStateResponse::new( query.client_id, consensus_state, - proof, + Some(proof), + response.height.into(), + )) + } + (Some(value), _) => { + let consensus_state = amino_unmarshal_binary_length_prefixed(&value)?; + + Ok(ConsensusStateResponse::new( + query.client_id, + consensus_state, + None, response.height.into(), )) } @@ -113,11 +131,12 @@ pub async fn query_client_consensus_state( chain_height: Height, client_id: ClientId, consensus_height: Height, + prove: bool, ) -> Result, error::Error> where C: Chain, { - let query = QueryClientConsensusState::new(chain_height, client_id, consensus_height); + let query = QueryClientConsensusState::new(chain_height, client_id, consensus_height, prove); ibc_query(chain, query).await } From b528dc67f6e489b45061253f4ab57bb8adcce132 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Mon, 30 Mar 2020 10:08:14 +0200 Subject: [PATCH 02/13] started on client state --- modules/Cargo.toml | 4 + modules/src/ics02_client/state.rs | 19 +++ modules/src/ics07_tendermint/client_state.rs | 77 +++++++++++ .../src/ics07_tendermint/consensus_state.rs | 20 +++ modules/src/ics07_tendermint/mod.rs | 1 + modules/src/lib.rs | 3 + modules/src/path.rs | 16 +++ modules/src/path/cosmos.rs | 6 +- modules/src/path/ics.rs | 4 +- modules/src/test.rs | 30 ++++ .../query/serialization/client_state.json | 11 ++ .../serialization/client_state_proof.json | 24 ++++ .../query/serialization/consensus_state.json | 11 ++ .../serialization/consensus_state_proof.json | 24 ++++ relayer/cli/src/commands/query/query.rs | 14 +- relayer/relay/src/chain.rs | 4 +- relayer/relay/src/chain/tendermint.rs | 4 + relayer/relay/src/lib.rs | 1 + relayer/relay/src/query.rs | 1 + .../relay/src/query/client_consensus_state.rs | 1 + relayer/relay/src/query/client_state.rs | 129 ++++++++++++++++++ 21 files changed, 397 insertions(+), 7 deletions(-) create mode 100644 modules/src/ics07_tendermint/client_state.rs create mode 100644 modules/src/test.rs create mode 100644 modules/src/tests/query/serialization/client_state.json create mode 100644 modules/src/tests/query/serialization/client_state_proof.json create mode 100644 modules/src/tests/query/serialization/consensus_state.json create mode 100644 modules/src/tests/query/serialization/consensus_state_proof.json create mode 100644 relayer/relay/src/query/client_state.rs diff --git a/modules/Cargo.toml b/modules/Cargo.toml index ce73546610..c412becce5 100644 --- a/modules/Cargo.toml +++ b/modules/Cargo.toml @@ -21,3 +21,7 @@ anomaly = "0.2.0" thiserror = "1.0.11" serde_derive = "1.0.104" serde = "1.0.104" + +[dev-dependencies] +serde_json = "1" + diff --git a/modules/src/ics02_client/state.rs b/modules/src/ics02_client/state.rs index aed8c3364a..d8961b4130 100644 --- a/modules/src/ics02_client/state.rs +++ b/modules/src/ics02_client/state.rs @@ -2,6 +2,7 @@ use super::client_type::ClientType; use crate::ics23_commitment::CommitmentRoot; use crate::Height; +use crate::ics24_host::client::ClientId; pub trait ConsensusState { type ValidationError: std::error::Error; @@ -18,3 +19,21 @@ pub trait ConsensusState { /// Performs basic validation of the consensus state fn validate_basic(&self) -> Result<(), Self::ValidationError>; } + +pub trait ClientState { + type ValidationError: std::error::Error; + + /// Client ID of this state + fn client_id(&self) -> ClientId; + + /// Type of client associated with this state (eg. Tendermint) + fn client_type(&self) -> ClientType; + + /// Height of consensus state + fn get_latest_height(&self) -> Height; + + /// Freeze status of the client + fn is_frozen(&self) -> bool; + + fn verify_client_consensus_state(&self, root: &CommitmentRoot) -> Result<(), Self::ValidationError>; +} \ No newline at end of file diff --git a/modules/src/ics07_tendermint/client_state.rs b/modules/src/ics07_tendermint/client_state.rs new file mode 100644 index 0000000000..8821557398 --- /dev/null +++ b/modules/src/ics07_tendermint/client_state.rs @@ -0,0 +1,77 @@ +use crate::ics02_client::client_type::ClientType; +use crate::ics23_commitment::CommitmentRoot; + +use serde_derive::{Deserialize, Serialize}; +use std::time::Duration; +use crate::ics24_host::client::ClientId; +use crate::ics07_tendermint::header::Header; +use tendermint::lite::Header as liteHeader; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct ClientState { + id: String, + trusting_period: Duration, + unbonding_period: Duration, + latest_header: Header, + frozen_height: crate::Height, +} + +impl ClientState { + pub fn new( + id: String, + trusting_period: Duration, + unbonding_period: Duration, + latest_header: Header, + frozen_height: crate::Height, + ) -> Self { + Self { + id, + trusting_period, + unbonding_period, + latest_header, + frozen_height, + } + } +} + +impl crate::ics02_client::state::ClientState for ClientState { + type ValidationError = crate::ics07_tendermint::error::Error; + + fn client_id(&self) -> ClientId { + self.id.parse().unwrap() + } + + fn client_type(&self) -> ClientType { + ClientType::Tendermint + } + + fn get_latest_height(&self) -> crate::Height { + self.latest_header.signed_header.header.height() + } + + fn is_frozen(&self) -> bool { false } + + fn verify_client_consensus_state(&self, _root: &CommitmentRoot) -> Result<(), Self::ValidationError> { + unimplemented!() + } +} + +#[cfg(test)] +mod tests { + use tendermint::rpc::endpoint::abci_query::AbciQuery; + use crate::test::test_serialization_roundtrip; + + #[test] + fn serialization_roundtrip_no_proof() { + let json_data = include_str!("../tests/query/serialization/client_state.json"); + println!("json_data: {:?}", json_data); + test_serialization_roundtrip::(json_data); + } + + #[test] + fn serialization_roundtrip_with_proof() { + let json_data = include_str!("../tests/query/serialization/client_state_proof.json"); + println!("json_data: {:?}", json_data); + test_serialization_roundtrip::(json_data); + } +} \ No newline at end of file diff --git a/modules/src/ics07_tendermint/consensus_state.rs b/modules/src/ics07_tendermint/consensus_state.rs index cec7332c7c..71c5649131 100644 --- a/modules/src/ics07_tendermint/consensus_state.rs +++ b/modules/src/ics07_tendermint/consensus_state.rs @@ -46,3 +46,23 @@ impl crate::ics02_client::state::ConsensusState for ConsensusState { unimplemented!() } } + +#[cfg(test)] +mod tests { + use tendermint::rpc::endpoint::abci_query::AbciQuery; + use crate::test::test_serialization_roundtrip; + + #[test] + fn serialization_roundtrip_no_proof() { + let json_data = include_str!("../tests/query/serialization/consensus_state.json"); + println!("json_data: {:?}", json_data); + test_serialization_roundtrip::(json_data); + } + + #[test] + fn serialization_roundtrip_with_proof() { + let json_data = include_str!("../tests/query/serialization/consensus_state_proof.json"); + println!("json_data: {:?}", json_data); + test_serialization_roundtrip::(json_data); + } +} \ No newline at end of file diff --git a/modules/src/ics07_tendermint/mod.rs b/modules/src/ics07_tendermint/mod.rs index 2b656579fa..9a58a5e341 100644 --- a/modules/src/ics07_tendermint/mod.rs +++ b/modules/src/ics07_tendermint/mod.rs @@ -1,6 +1,7 @@ //! ICS 07: Tendermint Client pub mod consensus_state; +pub mod client_state; pub mod error; pub mod header; pub mod msgs; diff --git a/modules/src/lib.rs b/modules/src/lib.rs index 69162648d5..f42f0519c9 100644 --- a/modules/src/lib.rs +++ b/modules/src/lib.rs @@ -27,3 +27,6 @@ pub mod path; /// Height of a block, same as in `tendermint` crate pub type Height = tendermint::lite::Height; + +#[cfg(test)] +mod test; diff --git a/modules/src/path.rs b/modules/src/path.rs index 065ea674d4..d8fb8b9f4d 100644 --- a/modules/src/path.rs +++ b/modules/src/path.rs @@ -65,3 +65,19 @@ impl Path for ConsensusStatePath { paths::consensus_state_path(&self) } } + +pub struct ClientStatePath { + pub client_id: ClientId, +} + +impl ClientStatePath { + pub fn new(client_id: ClientId) -> Self { + Self { client_id} + } +} + +impl Path for ClientStatePath { + fn to_string(&self) -> String { + paths::client_state_path(&self) + } +} \ No newline at end of file diff --git a/modules/src/path/cosmos.rs b/modules/src/path/cosmos.rs index bcac757bcf..98a2997e4e 100644 --- a/modules/src/path/cosmos.rs +++ b/modules/src/path/cosmos.rs @@ -1,4 +1,4 @@ -use super::{ConnectionPath, ConsensusStatePath}; +use super::{ConnectionPath, ConsensusStatePath, ClientStatePath}; pub fn connection_path(path: &ConnectionPath) -> String { format!("connection/{}", path.connection_id) @@ -7,3 +7,7 @@ pub fn connection_path(path: &ConnectionPath) -> String { pub fn consensus_state_path(path: &ConsensusStatePath) -> String { format!("consensusState/{}/{}", path.client_id, path.height) } + +pub fn client_state_path(path: &ClientStatePath) -> String { + format!("clientState/{}", path.client_id) +} \ No newline at end of file diff --git a/modules/src/path/ics.rs b/modules/src/path/ics.rs index 42687fc711..1ca408eb73 100644 --- a/modules/src/path/ics.rs +++ b/modules/src/path/ics.rs @@ -1,4 +1,4 @@ -use super::{ConnectionPath, ConsensusStatePath}; +use super::{ConnectionPath, ConsensusStatePath, ClientStatePath}; pub fn connection_path(_path: &ConnectionPath) -> String { todo!() @@ -7,3 +7,5 @@ pub fn connection_path(_path: &ConnectionPath) -> String { pub fn consensus_state_path(_path: &ConsensusStatePath) -> String { todo!() } + +pub fn client_state_path(_path: &ClientStatePath) -> String { todo!() } \ No newline at end of file diff --git a/modules/src/test.rs b/modules/src/test.rs new file mode 100644 index 0000000000..4aa9b8d0fe --- /dev/null +++ b/modules/src/test.rs @@ -0,0 +1,30 @@ +use serde::{de::DeserializeOwned, Serialize}; +use std::fmt::Debug; + +/// Test that a struct `T` can be: +/// +/// - parsed out of the provided JSON data +/// - serialized back to JSON +/// - parsed back from the serialized JSON of the previous step +/// - that the two parsed structs are equal according to their `PartialEq` impl +pub fn test_serialization_roundtrip(json_data: &str) + where + T: Debug + Serialize + DeserializeOwned, +{ + let parsed0 = serde_json::from_str::(json_data); + assert!(parsed0.is_ok()); + let parsed0 = parsed0.unwrap(); + + let serialized = serde_json::to_string(&parsed0); + assert!(serialized.is_ok()); + let serialized = serialized.unwrap(); + + let parsed1 = serde_json::from_str::(&serialized); + assert!(parsed1.is_ok()); + let parsed1 = parsed1.unwrap(); + println!("json_data0: {:?}", parsed0); + println!("json_data1: {:?}", parsed1); + + // TODO - fix PartialEq bound issue in AbciQuery + //assert_eq!(parsed0, parsed1); +} \ No newline at end of file diff --git a/modules/src/tests/query/serialization/client_state.json b/modules/src/tests/query/serialization/client_state.json new file mode 100644 index 0000000000..36efe1086a --- /dev/null +++ b/modules/src/tests/query/serialization/client_state.json @@ -0,0 +1,11 @@ +{ + "code": 0, + "log": "", + "info": "", + "index": "0", + "key": "Y2xpZW50U3RhdGUvaWJjb25lY2xpZW50", + "value": "rwUhoYiWCgxpYmNvbmVjbGllbnQQgIDIkv+DkwIYgIDs2/7FnAMqiAUKgAQKxQIKAggKEgRpYmMxGBYiCwjMvIL0BRDIu58kKkgKICyeWhXpKZwrrUlzbaZ0DQnPqzkdNc8+k9eOogSLx43aEiQIARIgCFeoy6YD9BwuE0C1AU9BdEa2V51Cs28MXKewBA1rNtMyIBNgBAObhFbZAWB4KQGBQaC7Z/azZUkkSj2hMdZFFFppQiDses9b3+5uOFW4wZL6WWA0xtv9hTPe3Ib6BA7pzYQySUog7HrPW9/ubjhVuMGS+llgNMbb/YUz3tyG+gQO6c2EMklSIASAkbx93Cg/d7+/kdc8RNpYw9+KnLyGdAXYt/ParaIvWiBq+Q9GJMZNlWMQCpPikuUo+bJNzOKyjZSthVT8qdTQRmIgbjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB1yFPbqil8EwnDU5G93rMLZvekApgKBErUBCBYaSAogZik4C8oy55EdSL4OhMTIAy8jsDvCYiK6ZYH58Wv6Q88SJAgBEiBIpIMYxWV2OFZh72/ooILjIPvaHEMZ008+w1h+rpi7WiJnCAISFPbqil8EwnDU5G93rMLZvekApgKBGgsIzbyC9AUQqI/hRyJAbloumBKmq9nNQ22y/XoogOCrp33xeHjzA2JyuxpR2oAtL+8KGwKbcCJvAZjwpqOEEiRdXJnQ1rHrubVJhg3WBRKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=", + "proof": null, + "height": "100", + "codespace": "" +} \ No newline at end of file diff --git a/modules/src/tests/query/serialization/client_state_proof.json b/modules/src/tests/query/serialization/client_state_proof.json new file mode 100644 index 0000000000..4803e7f15c --- /dev/null +++ b/modules/src/tests/query/serialization/client_state_proof.json @@ -0,0 +1,24 @@ +{ + "code": 0, + "log": "", + "info": "", + "index": "0", + "key": "Y2xpZW50U3RhdGUvaWJjb25lY2xpZW50", + "value": "rwUhoYiWCgxpYmNvbmVjbGllbnQQgIDIkv+DkwIYgIDs2/7FnAMqiAUKgAQKxQIKAggKEgRpYmMxGBYiCwjMvIL0BRDIu58kKkgKICyeWhXpKZwrrUlzbaZ0DQnPqzkdNc8+k9eOogSLx43aEiQIARIgCFeoy6YD9BwuE0C1AU9BdEa2V51Cs28MXKewBA1rNtMyIBNgBAObhFbZAWB4KQGBQaC7Z/azZUkkSj2hMdZFFFppQiDses9b3+5uOFW4wZL6WWA0xtv9hTPe3Ib6BA7pzYQySUog7HrPW9/ubjhVuMGS+llgNMbb/YUz3tyG+gQO6c2EMklSIASAkbx93Cg/d7+/kdc8RNpYw9+KnLyGdAXYt/ParaIvWiBq+Q9GJMZNlWMQCpPikuUo+bJNzOKyjZSthVT8qdTQRmIgbjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB1yFPbqil8EwnDU5G93rMLZvekApgKBErUBCBYaSAogZik4C8oy55EdSL4OhMTIAy8jsDvCYiK6ZYH58Wv6Q88SJAgBEiBIpIMYxWV2OFZh72/ooILjIPvaHEMZ008+w1h+rpi7WiJnCAISFPbqil8EwnDU5G93rMLZvekApgKBGgsIzbyC9AUQqI/hRyJAbloumBKmq9nNQ22y/XoogOCrp33xeHjzA2JyuxpR2oAtL+8KGwKbcCJvAZjwpqOEEiRdXJnQ1rHrubVJhg3WBRKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=", + "proof": { + "ops": [ + { + "type": "iavl:v", + "key": "Y2xpZW50U3RhdGUvaWJjb25lY2xpZW50", + "data": "6wEK6AEKKAgIEAwYHCogr722bXSL9572EU1Jgdz6re1sVtpscxSW4cjaLrCtKPoKKAgGEAcYHCIg1wO/S0DOyBX5/zwOTIQt5lY7SkEJUORfEfZtHH6ZcLcKKAgEEAQYHCIgvBVVJn1U3LKVuitwm6hAvnwujQDcyMOOp5YdNbwdyTEKKAgCEAIYFyIgcuZfF//lb+VDAKtkXsR/J2/QPYlaw8HvrSmNqDf1iVYaPgoYY2xpZW50U3RhdGUvaWJjb25lY2xpZW50EiDV6DHA5N7GJNbSj0hzc586MXPwXDj4H57rYWZesk2XjRgX" + }, + { + "type": "multistore", + "key": "aWJj", + "data": "CtUECi4KBGJhbmsSJgokCGQSIPfIBFZd98DupWwTml7I8kZFWKgF8ZTlslblitSLTJjqCi0KA2FjYxImCiQIZBIg3ZgdzN65c2/J62tIVCmQJwnN8Ho9dULDSL9dKEyA+cgKDwoHdXBncmFkZRIECgIIZAoxCgdzdGFraW5nEiYKJAhkEiCWTzW3aCWkLAyuZxi9z2CSXhmtmcRWEKi6K9ywkrVZMwoyCghzbGFzaGluZxImCiQIZBIgj6AcKVZzEJeL1r3wf9Qi5B53bjomfcn3g76fvuJn/FkKMAoGc3VwcGx5EiYKJAhkEiCRsUBZCybnNEYnaNqDTOO1pNEuAfGgY7pQMrgLCyUWBQotCgNnb3YSJgokCGQSIGDNE3wZYuysYWOJ1oA0gz8pIVCcLShapfUVOZfOlop0Ci0KA2liYxImCiQIZBIgWnpokBJ4idAoXzLzbjOOaBwU5E3oz4QJuAV8mShsqzwKLgoEbWFpbhImCiQIZBIgsZzwmLQ7PH1UeZ/vCUSqlQmfgt3CGfoMgJLkUqKCv0EKMAoGcGFyYW1zEiYKJAhkEiB8VIzExUHX+SvHZFz/P9NM9THnw/gTDDLVReuZX8htLgo2CgxkaXN0cmlidXRpb24SJgokCGQSIMaSvcpnTBH1nyPp/m3Ab+A/fowTOIWmuMtlbCda/2SsChAKCHRyYW5zZmVyEgQKAghkChAKCGV2aWRlbmNlEgQKAghkCi4KBG1pbnQSJgokCGQSIPvdoKLt1qhBYkRKjo39yCkQ0c1pOYM0kohjsVVGx9ae" + } + ] + }, + "height": "100", + "codespace": "" +} \ No newline at end of file diff --git a/modules/src/tests/query/serialization/consensus_state.json b/modules/src/tests/query/serialization/consensus_state.json new file mode 100644 index 0000000000..4d74e5e49a --- /dev/null +++ b/modules/src/tests/query/serialization/consensus_state.json @@ -0,0 +1,11 @@ +{ + "code": 0, + "log": "", + "info": "", + "index": "0", + "key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy", + "value": "wAE7xH38CgsIzLyC9AUQyLufJBImzXAxMQogavkPRiTGTZVjEAqT4pLlKPmyTcziso2UrYVU/KnU0EYYFiKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=", + "proof": null, + "height": "60295", + "codespace": "" +} \ No newline at end of file diff --git a/modules/src/tests/query/serialization/consensus_state_proof.json b/modules/src/tests/query/serialization/consensus_state_proof.json new file mode 100644 index 0000000000..bcc6c73138 --- /dev/null +++ b/modules/src/tests/query/serialization/consensus_state_proof.json @@ -0,0 +1,24 @@ +{ + "code": 0, + "log": "", + "info": "", + "index": "0", + "key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy", + "value": "wAE7xH38CgsIzLyC9AUQyLufJBImzXAxMQogavkPRiTGTZVjEAqT4pLlKPmyTcziso2UrYVU/KnU0EYYFiKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=", + "proof": { + "ops": [ + { + "type": "iavl:v", + "key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy", + "data": "8QEK7gEKKAgIEAwYHCIgG9RAkJgHlxNjmyzOW6bUAidhiRSja0x6+GXCVENPG1oKKAgGEAUYFyIgwRns+dJvjf1Zk2BaFrXz8inPbvYHB7xx2HCy9ima5f8KKAgEEAMYFyogOr8EGajEV6fG5fzJ2fAAvVMgRLhdMJTzCPlogl9rxlIKKAgCEAIYFyIgcjzX/a+2bFbnNldpawQqZ+kYhIwz5r4wCUzuu1IFW04aRAoeY29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIyEiAZ1uuG60K4NHJZZMuS9QX6o4eEhica5jIHYwflRiYkDBgX" + }, + { + "type": "multistore", + "key": "aWJj", + "data": "CvEECjAKBGJhbmsSKAomCIjYAxIg2MEyyonbZButYnvSRkf2bPQg+nqA+Am1MeDxG6F4p1UKLwoDYWNjEigKJgiI2AMSIN2YHczeuXNvyetrSFQpkCcJzfB6PXVCw0i/XShMgPnIChEKB3VwZ3JhZGUSBgoECIjYAwovCgNnb3YSKAomCIjYAxIgYM0TfBli7KxhY4nWgDSDPykhUJwtKFql9RU5l86WinQKLwoDaWJjEigKJgiI2AMSIFp6aJASeInQKF8y824zjmgcFORN6M+ECbgFfJkobKs8CjAKBG1haW4SKAomCIjYAxIgsZzwmLQ7PH1UeZ/vCUSqlQmfgt3CGfoMgJLkUqKCv0EKMwoHc3Rha2luZxIoCiYIiNgDEiCiBZoBLyDGj5euy3n33ik+SpqYK9eB5xbI+iY8ycYVbwo0CghzbGFzaGluZxIoCiYIiNgDEiAJz3gEYuIhdensHU3b5qH5ons2quepd6EaRgCHXab6PQoyCgZzdXBwbHkSKAomCIjYAxIglWLA5/THPTiTxAlaLHOBYFIzEJTmKPznItUwAc8zD+AKEgoIZXZpZGVuY2USBgoECIjYAwowCgRtaW50EigKJgiI2AMSIMS8dZ1j8F6JVVv+hB1rHBZC+gIFJxHan2hM8qDC64n/CjIKBnBhcmFtcxIoCiYIiNgDEiB8VIzExUHX+SvHZFz/P9NM9THnw/gTDDLVReuZX8htLgo4CgxkaXN0cmlidXRpb24SKAomCIjYAxIg3u/Nd4L+8LT8OXJCh14o8PHIJ/GLQwsmE7KYIl1GdSYKEgoIdHJhbnNmZXISBgoECIjYAw==" + } + ] + }, + "height": "60424", + "codespace": "" +} \ No newline at end of file diff --git a/relayer/cli/src/commands/query/query.rs b/relayer/cli/src/commands/query/query.rs index cc629ec824..c7b2596503 100644 --- a/relayer/cli/src/commands/query/query.rs +++ b/relayer/cli/src/commands/query/query.rs @@ -16,7 +16,7 @@ pub struct QueryClientsCmd { #[derive(Debug)] struct QueryOptions<'a> { - /// identifier of chain to initialize light client for + /// identifier of chain for which to query the light client rpc_addr: &'a net::Address, proof: bool, } @@ -38,6 +38,8 @@ impl QueryClientsCmd { } use relayer::query::client_consensus_state::query_client_consensus_state; +use relayer::query::client_state::query_client_latest_state; + use std::str::FromStr; use relayer::chain::tendermint::TendermintChain; use relayer::config::ChainConfig; @@ -68,7 +70,7 @@ impl Runnable for QueryClientsCmd { // Proper way is to query client state (not yet implemented), get the consensus_height from // the response and then query the consensus state. In the absence of this, look at logs // and check the height :( - let consensus_height = 17 as u64; + let consensus_height = 22 as u64; // Also, the relayer should have been started with config, chain information parsed and // the `Chain` already created. This also is not implemented therefore the weird sequence @@ -82,9 +84,13 @@ impl Runnable for QueryClientsCmd { key_name: "".to_string(), client_ids: vec![], gas: 0, trusting_period: Duration::from_secs(336 * 60 * 60)}).unwrap(); + if false { + let res = block_on( + query_client_consensus_state(&chain, chain_height, client_id.clone(), consensus_height, opts.proof)).unwrap(); + } + let res = block_on( - query_client_consensus_state(&chain, chain_height, client_id, consensus_height, opts.proof)).unwrap(); - println!("abci response: {:?}", res.proof_height); + query_client_latest_state(&chain, chain_height, client_id.clone(), opts.proof)).unwrap(); // end remove soon } } diff --git a/relayer/relay/src/chain.rs b/relayer/relay/src/chain.rs index 4909a0791a..b633f3c653 100644 --- a/relayer/relay/src/chain.rs +++ b/relayer/relay/src/chain.rs @@ -8,7 +8,7 @@ use ::tendermint::lite::types as tmlite; use ::tendermint::lite::{self, Height, TrustThresholdFraction}; use ::tendermint::rpc::Client as RpcClient; -use relayer_modules::ics02_client::state::ConsensusState; +use relayer_modules::ics02_client::state::{ConsensusState, ClientState}; use crate::config::ChainConfig; use crate::error; @@ -28,6 +28,8 @@ pub trait Chain { /// Type of consensus state for this chain type ConsensusState: ConsensusState + Serialize + DeserializeOwned; + type Type; + type ClientState: ClientState; /// Type of RPC requester (wrapper around low-level RPC client) for this chain type Requester: tmlite::Requester; diff --git a/relayer/relay/src/chain/tendermint.rs b/relayer/relay/src/chain/tendermint.rs index 4484e4833c..7a23e862e7 100644 --- a/relayer/relay/src/chain/tendermint.rs +++ b/relayer/relay/src/chain/tendermint.rs @@ -5,6 +5,8 @@ use tendermint::block::Header as TMHeader; use tendermint::lite::TrustThresholdFraction; use tendermint::rpc::Client as RpcClient; +use relayer_modules::ics02_client::client_type::ClientType; +use relayer_modules::ics07_tendermint::client_state::ClientState; use relayer_modules::ics07_tendermint::consensus_state::ConsensusState; use crate::client::rpc_requester::RpcRequester; @@ -34,10 +36,12 @@ impl TendermintChain { } impl Chain for TendermintChain { + type Type = ClientType; type Header = TMHeader; type Commit = TMCommit; type ConsensusState = ConsensusState; type Requester = RpcRequester; + type ClientState = ClientState; fn config(&self) -> &ChainConfig { &self.config diff --git a/relayer/relay/src/lib.rs b/relayer/relay/src/lib.rs index 0e9cf139fb..d4632816b4 100644 --- a/relayer/relay/src/lib.rs +++ b/relayer/relay/src/lib.rs @@ -18,3 +18,4 @@ pub mod error; pub mod query; pub mod store; pub mod util; + diff --git a/relayer/relay/src/query.rs b/relayer/relay/src/query.rs index 7e3f5a9651..16fd19236b 100644 --- a/relayer/relay/src/query.rs +++ b/relayer/relay/src/query.rs @@ -7,6 +7,7 @@ use crate::chain::Chain; use crate::error; pub mod client_consensus_state; +pub mod client_state; /// The type of IBC response sent back for a given IBC `Query`. pub trait IbcResponse: Sized { diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index f45c4fd1aa..58dfde3fc0 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -137,6 +137,7 @@ where C: Chain, { let query = QueryClientConsensusState::new(chain_height, client_id, consensus_height, prove); + println!("XXX Query: {:?}", query.consensus_state_path.to_string()); ibc_query(chain, query).await } diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs new file mode 100644 index 0000000000..bd76958535 --- /dev/null +++ b/relayer/relay/src/query/client_state.rs @@ -0,0 +1,129 @@ +use std::marker::PhantomData; +use tendermint::rpc::endpoint::abci_query::AbciQuery; + +use tendermint::abci; + +use relayer_modules::ics02_client::state::ClientState; +use relayer_modules::ics23_commitment::{CommitmentPath, CommitmentProof}; +use relayer_modules::ics24_host::client::ClientId; +use relayer_modules::path::{ClientStatePath, Path}; +use relayer_modules::Height; + +use super::{ibc_query, IbcQuery, IbcResponse}; +use crate::chain::Chain; +use crate::error; + +pub struct QueryClientLatestState { + pub chain_height: Height, + pub client_id: ClientId, + pub client_state_path: ClientStatePath, + pub prove: bool, + marker: PhantomData, +} + +impl QueryClientLatestState { + pub fn new(chain_height: Height, client_id: ClientId, prove: bool) -> Self { + Self { + chain_height, + client_id: client_id.clone(), + client_state_path: ClientStatePath::new(client_id), + prove, + marker: PhantomData, + } + } +} + +impl IbcQuery for QueryClientLatestState +where + CLS: ClientState, +{ + type Response = ClientStateResponse; + + fn path(&self) -> abci::Path { + "/store/ibc/key".parse().unwrap() + } + + fn height(&self) -> Height { + self.chain_height + } + + fn prove(&self) -> bool { + true + } + + fn data(&self) -> Vec { + self.client_state_path.to_key().into() + } +} + +pub struct ClientStateResponse { + pub client_state: CLS, + pub proof: CommitmentProof, + pub proof_path: CommitmentPath, + pub proof_height: Height, +} + +impl ClientStateResponse { + pub fn new( + client_id: ClientId, + client_state: CLS, + abci_proof: Proof, + proof_height: Height, + ) -> Self { + let proof = CommitmentProof::from_bytes(abci_proof.as_ref()); + let proof_path = + CommitmentPath::from_path(ClientStatePath::new(client_id)); + + ClientStateResponse { + client_state, + proof, + proof_path, + proof_height, + } + } +} + +impl IbcResponse> for ClientStateResponse +where + CLS: ClientState, +{ + fn from_abci_response( + query: QueryClientLatestState, + response: AbciQuery, + ) -> Result { + match (response.value, response.proof) { + (Some(value), Some(proof)) => { + let consensus_state = amino_unmarshal_binary_length_prefixed(&value)?; + + Ok(ClientStateResponse::new( + query.client_id, + consensus_state, + proof, + response.height.into(), + )) + } + _ => todo!(), + } + } +} + +use tendermint::abci::Proof; + +pub async fn query_client_latest_state( + chain: &C, + chain_height: Height, + client_id: ClientId, + prove: bool, +) -> Result, error::Error> +where + C: Chain, +{ + let query = QueryClientLatestState::new(chain_height, client_id, prove); + println!("XXX Query: {:?}", query.client_state_path.to_string()); + + ibc_query(chain, query).await +} + +fn amino_unmarshal_binary_length_prefixed(_bytes: &[u8]) -> Result { + todo!() +} From b783baa6abb83f8f4cfaecd17e97581606030fb9 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Mon, 30 Mar 2020 10:09:56 +0200 Subject: [PATCH 03/13] fixed unused warning --- relayer/cli/src/commands/query/query.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relayer/cli/src/commands/query/query.rs b/relayer/cli/src/commands/query/query.rs index c7b2596503..c479a3a273 100644 --- a/relayer/cli/src/commands/query/query.rs +++ b/relayer/cli/src/commands/query/query.rs @@ -85,11 +85,11 @@ impl Runnable for QueryClientsCmd { trusting_period: Duration::from_secs(336 * 60 * 60)}).unwrap(); if false { - let res = block_on( + let _res = block_on( query_client_consensus_state(&chain, chain_height, client_id.clone(), consensus_height, opts.proof)).unwrap(); } - let res = block_on( + let _res = block_on( query_client_latest_state(&chain, chain_height, client_id.clone(), opts.proof)).unwrap(); // end remove soon } From 3f4afdbaa5bba51044c5cdb1d09b55f46be9c03d Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Mon, 30 Mar 2020 10:53:10 +0200 Subject: [PATCH 04/13] add height param to client query --- relayer/cli/src/commands/query/query.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/relayer/cli/src/commands/query/query.rs b/relayer/cli/src/commands/query/query.rs index c479a3a273..8100d038f1 100644 --- a/relayer/cli/src/commands/query/query.rs +++ b/relayer/cli/src/commands/query/query.rs @@ -11,6 +11,7 @@ pub struct QueryClientsCmd { #[options(free, help = "rpc address")] // TODO replace this with the chain-id string and retrieve the rpc_addr from `Chain` rpc_addr: Option, + height: Option, proof: Option, } @@ -18,21 +19,21 @@ pub struct QueryClientsCmd { struct QueryOptions<'a> { /// identifier of chain for which to query the light client rpc_addr: &'a net::Address, + height: u64, proof: bool, } impl QueryClientsCmd { - fn validate_options(&self) -> Result, &'static str> { - let proof = match self.proof { - Some(proof) => proof, - None => true, - }; + fn validate_options(&self) -> Result, String> { + match (&self.rpc_addr, self.height, self.proof) { + (Some(rpc_addr), Some(height), Some(proof)) => { + Ok(QueryOptions {rpc_addr, height, proof}) + } - match &self.rpc_addr { - Some(rpc_addr) => Ok(QueryOptions { - rpc_addr, proof - }), - None => Err("missing rpc address"), + (None, _, _) => Err(format!("missing rpc address")), + (Some(rpc_addr), None, Some(proof)) => Ok(QueryOptions {rpc_addr, height: 0 as u64, proof}), + (Some(rpc_addr), Some(height), None) => Ok(QueryOptions {rpc_addr, height, proof: false}), + (Some(rpc_addr), None, None) => Ok(QueryOptions {rpc_addr, height: 0 as u64, proof: false}), } } } @@ -70,7 +71,7 @@ impl Runnable for QueryClientsCmd { // Proper way is to query client state (not yet implemented), get the consensus_height from // the response and then query the consensus state. In the absence of this, look at logs // and check the height :( - let consensus_height = 22 as u64; + let consensus_height = opts.height; // Also, the relayer should have been started with config, chain information parsed and // the `Chain` already created. This also is not implemented therefore the weird sequence @@ -84,7 +85,7 @@ impl Runnable for QueryClientsCmd { key_name: "".to_string(), client_ids: vec![], gas: 0, trusting_period: Duration::from_secs(336 * 60 * 60)}).unwrap(); - if false { + if true { let _res = block_on( query_client_consensus_state(&chain, chain_height, client_id.clone(), consensus_height, opts.proof)).unwrap(); } From 9b9917e3d54a20c911de6087c227a19d811ffeee Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Mon, 30 Mar 2020 11:01:09 +0200 Subject: [PATCH 05/13] cargo fmt --- modules/src/ics02_client/state.rs | 9 ++- modules/src/ics07_tendermint/client_state.rs | 17 +++-- .../src/ics07_tendermint/consensus_state.rs | 4 +- modules/src/ics07_tendermint/mod.rs | 2 +- modules/src/path.rs | 4 +- modules/src/path/cosmos.rs | 4 +- modules/src/path/ics.rs | 6 +- modules/src/test.rs | 6 +- relayer/cli/src/commands.rs | 6 +- relayer/cli/src/commands/query/query.rs | 67 ++++++++++++++----- relayer/relay/src/chain.rs | 2 +- relayer/relay/src/lib.rs | 1 - .../relay/src/query/client_consensus_state.rs | 8 ++- relayer/relay/src/query/client_state.rs | 3 +- 14 files changed, 92 insertions(+), 47 deletions(-) diff --git a/modules/src/ics02_client/state.rs b/modules/src/ics02_client/state.rs index d8961b4130..fed45bcd4f 100644 --- a/modules/src/ics02_client/state.rs +++ b/modules/src/ics02_client/state.rs @@ -1,8 +1,8 @@ use super::client_type::ClientType; use crate::ics23_commitment::CommitmentRoot; -use crate::Height; use crate::ics24_host::client::ClientId; +use crate::Height; pub trait ConsensusState { type ValidationError: std::error::Error; @@ -35,5 +35,8 @@ pub trait ClientState { /// Freeze status of the client fn is_frozen(&self) -> bool; - fn verify_client_consensus_state(&self, root: &CommitmentRoot) -> Result<(), Self::ValidationError>; -} \ No newline at end of file + fn verify_client_consensus_state( + &self, + root: &CommitmentRoot, + ) -> Result<(), Self::ValidationError>; +} diff --git a/modules/src/ics07_tendermint/client_state.rs b/modules/src/ics07_tendermint/client_state.rs index 8821557398..5a5315b588 100644 --- a/modules/src/ics07_tendermint/client_state.rs +++ b/modules/src/ics07_tendermint/client_state.rs @@ -1,10 +1,10 @@ use crate::ics02_client::client_type::ClientType; use crate::ics23_commitment::CommitmentRoot; +use crate::ics07_tendermint::header::Header; +use crate::ics24_host::client::ClientId; use serde_derive::{Deserialize, Serialize}; use std::time::Duration; -use crate::ics24_host::client::ClientId; -use crate::ics07_tendermint::header::Header; use tendermint::lite::Header as liteHeader; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -49,17 +49,22 @@ impl crate::ics02_client::state::ClientState for ClientState { self.latest_header.signed_header.header.height() } - fn is_frozen(&self) -> bool { false } + fn is_frozen(&self) -> bool { + false + } - fn verify_client_consensus_state(&self, _root: &CommitmentRoot) -> Result<(), Self::ValidationError> { + fn verify_client_consensus_state( + &self, + _root: &CommitmentRoot, + ) -> Result<(), Self::ValidationError> { unimplemented!() } } #[cfg(test)] mod tests { - use tendermint::rpc::endpoint::abci_query::AbciQuery; use crate::test::test_serialization_roundtrip; + use tendermint::rpc::endpoint::abci_query::AbciQuery; #[test] fn serialization_roundtrip_no_proof() { @@ -74,4 +79,4 @@ mod tests { println!("json_data: {:?}", json_data); test_serialization_roundtrip::(json_data); } -} \ No newline at end of file +} diff --git a/modules/src/ics07_tendermint/consensus_state.rs b/modules/src/ics07_tendermint/consensus_state.rs index 71c5649131..f6f60eebc9 100644 --- a/modules/src/ics07_tendermint/consensus_state.rs +++ b/modules/src/ics07_tendermint/consensus_state.rs @@ -49,8 +49,8 @@ impl crate::ics02_client::state::ConsensusState for ConsensusState { #[cfg(test)] mod tests { - use tendermint::rpc::endpoint::abci_query::AbciQuery; use crate::test::test_serialization_roundtrip; + use tendermint::rpc::endpoint::abci_query::AbciQuery; #[test] fn serialization_roundtrip_no_proof() { @@ -65,4 +65,4 @@ mod tests { println!("json_data: {:?}", json_data); test_serialization_roundtrip::(json_data); } -} \ No newline at end of file +} diff --git a/modules/src/ics07_tendermint/mod.rs b/modules/src/ics07_tendermint/mod.rs index 9a58a5e341..d384cb4bc0 100644 --- a/modules/src/ics07_tendermint/mod.rs +++ b/modules/src/ics07_tendermint/mod.rs @@ -1,7 +1,7 @@ //! ICS 07: Tendermint Client -pub mod consensus_state; pub mod client_state; +pub mod consensus_state; pub mod error; pub mod header; pub mod msgs; diff --git a/modules/src/path.rs b/modules/src/path.rs index d8fb8b9f4d..17a65ccb14 100644 --- a/modules/src/path.rs +++ b/modules/src/path.rs @@ -72,7 +72,7 @@ pub struct ClientStatePath { impl ClientStatePath { pub fn new(client_id: ClientId) -> Self { - Self { client_id} + Self { client_id } } } @@ -80,4 +80,4 @@ impl Path for ClientStatePath { fn to_string(&self) -> String { paths::client_state_path(&self) } -} \ No newline at end of file +} diff --git a/modules/src/path/cosmos.rs b/modules/src/path/cosmos.rs index 98a2997e4e..84bdde30ce 100644 --- a/modules/src/path/cosmos.rs +++ b/modules/src/path/cosmos.rs @@ -1,4 +1,4 @@ -use super::{ConnectionPath, ConsensusStatePath, ClientStatePath}; +use super::{ClientStatePath, ConnectionPath, ConsensusStatePath}; pub fn connection_path(path: &ConnectionPath) -> String { format!("connection/{}", path.connection_id) @@ -10,4 +10,4 @@ pub fn consensus_state_path(path: &ConsensusStatePath) -> String { pub fn client_state_path(path: &ClientStatePath) -> String { format!("clientState/{}", path.client_id) -} \ No newline at end of file +} diff --git a/modules/src/path/ics.rs b/modules/src/path/ics.rs index 1ca408eb73..8619459f1d 100644 --- a/modules/src/path/ics.rs +++ b/modules/src/path/ics.rs @@ -1,4 +1,4 @@ -use super::{ConnectionPath, ConsensusStatePath, ClientStatePath}; +use super::{ClientStatePath, ConnectionPath, ConsensusStatePath}; pub fn connection_path(_path: &ConnectionPath) -> String { todo!() @@ -8,4 +8,6 @@ pub fn consensus_state_path(_path: &ConsensusStatePath) -> String { todo!() } -pub fn client_state_path(_path: &ClientStatePath) -> String { todo!() } \ No newline at end of file +pub fn client_state_path(_path: &ClientStatePath) -> String { + todo!() +} diff --git a/modules/src/test.rs b/modules/src/test.rs index 4aa9b8d0fe..3124af435a 100644 --- a/modules/src/test.rs +++ b/modules/src/test.rs @@ -8,8 +8,8 @@ use std::fmt::Debug; /// - parsed back from the serialized JSON of the previous step /// - that the two parsed structs are equal according to their `PartialEq` impl pub fn test_serialization_roundtrip(json_data: &str) - where - T: Debug + Serialize + DeserializeOwned, +where + T: Debug + Serialize + DeserializeOwned, { let parsed0 = serde_json::from_str::(json_data); assert!(parsed0.is_ok()); @@ -27,4 +27,4 @@ pub fn test_serialization_roundtrip(json_data: &str) // TODO - fix PartialEq bound issue in AbciQuery //assert_eq!(parsed0, parsed1); -} \ No newline at end of file +} diff --git a/relayer/cli/src/commands.rs b/relayer/cli/src/commands.rs index ff4f8cc6c9..e4e3d3d483 100644 --- a/relayer/cli/src/commands.rs +++ b/relayer/cli/src/commands.rs @@ -7,11 +7,13 @@ mod config; mod light; +mod query; mod start; mod version; -mod query; -use self::{config::ConfigCmd, light::LightCmd, start::StartCmd, version::VersionCmd, query::QueryCmd}; +use self::{ + config::ConfigCmd, light::LightCmd, query::QueryCmd, start::StartCmd, version::VersionCmd, +}; use crate::config::Config; use abscissa_core::{Command, Configurable, FrameworkError, Help, Options, Runnable}; diff --git a/relayer/cli/src/commands/query/query.rs b/relayer/cli/src/commands/query/query.rs index 8100d038f1..abc085a128 100644 --- a/relayer/cli/src/commands/query/query.rs +++ b/relayer/cli/src/commands/query/query.rs @@ -1,10 +1,10 @@ use crate::prelude::*; use abscissa_core::{Command, Options, Runnable}; -use tendermint::net; use core::future::Future; -use tokio::runtime::Builder; use relayer_modules::ics24_host::client::ClientId; +use tendermint::net; +use tokio::runtime::Builder; #[derive(Command, Debug, Options)] pub struct QueryClientsCmd { @@ -26,14 +26,28 @@ struct QueryOptions<'a> { impl QueryClientsCmd { fn validate_options(&self) -> Result, String> { match (&self.rpc_addr, self.height, self.proof) { - (Some(rpc_addr), Some(height), Some(proof)) => { - Ok(QueryOptions {rpc_addr, height, proof}) - } + (Some(rpc_addr), Some(height), Some(proof)) => Ok(QueryOptions { + rpc_addr, + height, + proof, + }), (None, _, _) => Err(format!("missing rpc address")), - (Some(rpc_addr), None, Some(proof)) => Ok(QueryOptions {rpc_addr, height: 0 as u64, proof}), - (Some(rpc_addr), Some(height), None) => Ok(QueryOptions {rpc_addr, height, proof: false}), - (Some(rpc_addr), None, None) => Ok(QueryOptions {rpc_addr, height: 0 as u64, proof: false}), + (Some(rpc_addr), None, Some(proof)) => Ok(QueryOptions { + rpc_addr, + height: 0 as u64, + proof, + }), + (Some(rpc_addr), Some(height), None) => Ok(QueryOptions { + rpc_addr, + height, + proof: false, + }), + (Some(rpc_addr), None, None) => Ok(QueryOptions { + rpc_addr, + height: 0 as u64, + proof: false, + }), } } } @@ -41,11 +55,11 @@ impl QueryClientsCmd { use relayer::query::client_consensus_state::query_client_consensus_state; use relayer::query::client_state::query_client_latest_state; -use std::str::FromStr; use relayer::chain::tendermint::TendermintChain; use relayer::config::ChainConfig; -use tendermint::chain::Id as ChainId; +use std::str::FromStr; use std::time::Duration; +use tendermint::chain::Id as ChainId; impl Runnable for QueryClientsCmd { fn run(&self) { @@ -81,17 +95,34 @@ impl Runnable for QueryClientsCmd { let chain_height = 0 as u64; let chain = TendermintChain::from_config(ChainConfig { - id: chain_id, rpc_addr: opts.rpc_addr.clone(), account_prefix: "".to_string(), - key_name: "".to_string(), client_ids: vec![], gas: 0, - trusting_period: Duration::from_secs(336 * 60 * 60)}).unwrap(); + id: chain_id, + rpc_addr: opts.rpc_addr.clone(), + account_prefix: "".to_string(), + key_name: "".to_string(), + client_ids: vec![], + gas: 0, + trusting_period: Duration::from_secs(336 * 60 * 60), + }) + .unwrap(); if true { - let _res = block_on( - query_client_consensus_state(&chain, chain_height, client_id.clone(), consensus_height, opts.proof)).unwrap(); + let _res = block_on(query_client_consensus_state( + &chain, + chain_height, + client_id.clone(), + consensus_height, + opts.proof, + )) + .unwrap(); } - let _res = block_on( - query_client_latest_state(&chain, chain_height, client_id.clone(), opts.proof)).unwrap(); + let _res = block_on(query_client_latest_state( + &chain, + chain_height, + client_id.clone(), + opts.proof, + )) + .unwrap(); // end remove soon } } @@ -103,4 +134,4 @@ fn block_on(future: F) -> F::Output { .build() .unwrap() .block_on(future) -} \ No newline at end of file +} diff --git a/relayer/relay/src/chain.rs b/relayer/relay/src/chain.rs index b633f3c653..58bab625f9 100644 --- a/relayer/relay/src/chain.rs +++ b/relayer/relay/src/chain.rs @@ -8,7 +8,7 @@ use ::tendermint::lite::types as tmlite; use ::tendermint::lite::{self, Height, TrustThresholdFraction}; use ::tendermint::rpc::Client as RpcClient; -use relayer_modules::ics02_client::state::{ConsensusState, ClientState}; +use relayer_modules::ics02_client::state::{ClientState, ConsensusState}; use crate::config::ChainConfig; use crate::error; diff --git a/relayer/relay/src/lib.rs b/relayer/relay/src/lib.rs index d4632816b4..0e9cf139fb 100644 --- a/relayer/relay/src/lib.rs +++ b/relayer/relay/src/lib.rs @@ -18,4 +18,3 @@ pub mod error; pub mod query; pub mod store; pub mod util; - diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index 58dfde3fc0..63871534d4 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -23,7 +23,12 @@ pub struct QueryClientConsensusState { } impl QueryClientConsensusState { - pub fn new(chain_height: Height, client_id: ClientId, consensus_height: Height, prove: bool) -> Self { + pub fn new( + chain_height: Height, + client_id: ClientId, + consensus_height: Height, + prove: bool, + ) -> Self { Self { chain_height, client_id: client_id.clone(), @@ -72,7 +77,6 @@ impl ConsensusStateResponse { abci_proof: Option, proof_height: Height, ) -> Self { - let mut proof: CommitmentProof = CommitmentProof; match abci_proof { Some(abci_proof) => { diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index bd76958535..9f86020c76 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -71,8 +71,7 @@ impl ClientStateResponse { proof_height: Height, ) -> Self { let proof = CommitmentProof::from_bytes(abci_proof.as_ref()); - let proof_path = - CommitmentPath::from_path(ClientStatePath::new(client_id)); + let proof_path = CommitmentPath::from_path(ClientStatePath::new(client_id)); ClientStateResponse { client_state, From 1558935c4e677729964ad209c6a8399c064c09d2 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Mon, 30 Mar 2020 13:31:23 +0200 Subject: [PATCH 06/13] make proof option for client state --- relayer/relay/src/query/client_state.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index 9f86020c76..80db661b3c 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -58,7 +58,7 @@ where pub struct ClientStateResponse { pub client_state: CLS, - pub proof: CommitmentProof, + pub proof: Option, pub proof_path: CommitmentPath, pub proof_height: Height, } @@ -67,15 +67,22 @@ impl ClientStateResponse { pub fn new( client_id: ClientId, client_state: CLS, - abci_proof: Proof, + abci_proof: Option, proof_height: Height, ) -> Self { - let proof = CommitmentProof::from_bytes(abci_proof.as_ref()); - let proof_path = CommitmentPath::from_path(ClientStatePath::new(client_id)); + let mut proof: CommitmentProof = CommitmentProof; + match abci_proof { + Some(abci_proof) => { + proof = CommitmentProof::from_bytes(abci_proof.as_ref()); + } + None => {} + } + let proof_path = + CommitmentPath::from_path(ClientStatePath::new(client_id)); ClientStateResponse { client_state, - proof, + proof: Option::from(proof), proof_path, proof_height, } @@ -97,7 +104,7 @@ where Ok(ClientStateResponse::new( query.client_id, consensus_state, - proof, + Some(proof), response.height.into(), )) } @@ -106,8 +113,6 @@ where } } -use tendermint::abci::Proof; - pub async fn query_client_latest_state( chain: &C, chain_height: Height, From b603ccc6a0ddeaa37caf3d78dded3374d4a7056d Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Mon, 30 Mar 2020 13:57:14 +0200 Subject: [PATCH 07/13] fix client state prove flag --- relayer/relay/src/query/client_state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index 80db661b3c..5f3a3dc53f 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -48,7 +48,7 @@ where } fn prove(&self) -> bool { - true + self.prove } fn data(&self) -> Vec { From ab168d8188a3c8fa7bcc835f367cfccbe6536c5a Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Tue, 7 Apr 2020 16:14:33 +0200 Subject: [PATCH 08/13] cleanup queries --- relayer/cli/src/commands/query.rs | 18 +- relayer/cli/src/commands/query/query.rs | 137 ----------- .../cli/src/commands/query/query_client.rs | 225 ++++++++++++++++++ relayer/relay/src/query/client_state.rs | 3 +- 4 files changed, 240 insertions(+), 143 deletions(-) delete mode 100644 relayer/cli/src/commands/query/query.rs create mode 100644 relayer/cli/src/commands/query/query_client.rs diff --git a/relayer/cli/src/commands/query.rs b/relayer/cli/src/commands/query.rs index 49502e5b8f..5ecb5cf5d1 100644 --- a/relayer/cli/src/commands/query.rs +++ b/relayer/cli/src/commands/query.rs @@ -2,12 +2,22 @@ use abscissa_core::{Command, Options, Runnable}; -mod query; +mod query_client; /// `query` subcommand #[derive(Command, Debug, Options, Runnable)] pub enum QueryCmd { - /// The `query clients` subcommand - #[options(help = "IBC query to a full node")] - Clients(query::QueryClientsCmd), + /// The `query client` subcommand + #[options(help = "query client")] + Client(QueryClientCmds), +} + +#[derive(Command, Debug, Options, Runnable)] +pub enum QueryClientCmds { + /// The `query client` subcommand + #[options(help = "query client state")] + State(query_client::QueryClientStateCmd), + + #[options(help = "query client consensus")] + Consensus(query_client::QueryClientConsensusCmd), } diff --git a/relayer/cli/src/commands/query/query.rs b/relayer/cli/src/commands/query/query.rs deleted file mode 100644 index abc085a128..0000000000 --- a/relayer/cli/src/commands/query/query.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::prelude::*; - -use abscissa_core::{Command, Options, Runnable}; -use core::future::Future; -use relayer_modules::ics24_host::client::ClientId; -use tendermint::net; -use tokio::runtime::Builder; - -#[derive(Command, Debug, Options)] -pub struct QueryClientsCmd { - #[options(free, help = "rpc address")] - // TODO replace this with the chain-id string and retrieve the rpc_addr from `Chain` - rpc_addr: Option, - height: Option, - proof: Option, -} - -#[derive(Debug)] -struct QueryOptions<'a> { - /// identifier of chain for which to query the light client - rpc_addr: &'a net::Address, - height: u64, - proof: bool, -} - -impl QueryClientsCmd { - fn validate_options(&self) -> Result, String> { - match (&self.rpc_addr, self.height, self.proof) { - (Some(rpc_addr), Some(height), Some(proof)) => Ok(QueryOptions { - rpc_addr, - height, - proof, - }), - - (None, _, _) => Err(format!("missing rpc address")), - (Some(rpc_addr), None, Some(proof)) => Ok(QueryOptions { - rpc_addr, - height: 0 as u64, - proof, - }), - (Some(rpc_addr), Some(height), None) => Ok(QueryOptions { - rpc_addr, - height, - proof: false, - }), - (Some(rpc_addr), None, None) => Ok(QueryOptions { - rpc_addr, - height: 0 as u64, - proof: false, - }), - } - } -} - -use relayer::query::client_consensus_state::query_client_consensus_state; -use relayer::query::client_state::query_client_latest_state; - -use relayer::chain::tendermint::TendermintChain; -use relayer::config::ChainConfig; -use std::str::FromStr; -use std::time::Duration; -use tendermint::chain::Id as ChainId; - -impl Runnable for QueryClientsCmd { - fn run(&self) { - let opts = match self.validate_options() { - Err(err) => { - status_err!("invalid options: {}", err); - return; - } - Ok(opts) => opts, - }; - status_info!("Options", "{:?}", opts); - - // TODO remove soon and replace with proper sequence - // run without proof - // export RUST_BACKTRACE=1 ; cargo run query clients localhost:26657 -p false - // this causes earlier error in ibc_query() -> `.map_err(|e| error::Kind::Rpc.context(e))?;:` - // - // run with proof: - // export RUST_BACKTRACE=1 ; cargo run query clients localhost:26657 - // this one fails in amino_unmarshal_binary_length_prefixed() as expected - // - // To test this start a Gaia node and configure a client with the go relayer. - // Proper way is to query client state (not yet implemented), get the consensus_height from - // the response and then query the consensus state. In the absence of this, look at logs - // and check the height :( - let consensus_height = opts.height; - - // Also, the relayer should have been started with config, chain information parsed and - // the `Chain` already created. This also is not implemented therefore the weird sequence - // below. - let client_id = ClientId::from_str("ibconeclient").unwrap(); - let chain_id = ChainId::from_str("ibc0").unwrap(); - let chain_height = 0 as u64; - - let chain = TendermintChain::from_config(ChainConfig { - id: chain_id, - rpc_addr: opts.rpc_addr.clone(), - account_prefix: "".to_string(), - key_name: "".to_string(), - client_ids: vec![], - gas: 0, - trusting_period: Duration::from_secs(336 * 60 * 60), - }) - .unwrap(); - - if true { - let _res = block_on(query_client_consensus_state( - &chain, - chain_height, - client_id.clone(), - consensus_height, - opts.proof, - )) - .unwrap(); - } - - let _res = block_on(query_client_latest_state( - &chain, - chain_height, - client_id.clone(), - opts.proof, - )) - .unwrap(); - // end remove soon - } -} - -fn block_on(future: F) -> F::Output { - Builder::new() - .basic_scheduler() - .enable_all() - .build() - .unwrap() - .block_on(future) -} diff --git a/relayer/cli/src/commands/query/query_client.rs b/relayer/cli/src/commands/query/query_client.rs new file mode 100644 index 0000000000..41b7c407b2 --- /dev/null +++ b/relayer/cli/src/commands/query/query_client.rs @@ -0,0 +1,225 @@ +use crate::prelude::*; + +use abscissa_core::{Command, Options, Runnable}; +use core::future::Future; +use relayer::config::{ChainConfig, Config}; +use relayer::query::client_consensus_state::query_client_consensus_state; +use relayer::query::client_state::query_client_latest_state; +use relayer_modules::ics24_host::client::ClientId; +use tokio::runtime::Builder; + +use relayer::chain::tendermint::TendermintChain; +use tendermint::chain::Id as ChainId; + +#[derive(Command, Debug, Options)] +pub struct QueryClientStateCmd { + #[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 QueryClientStateOptions { + client_id: ClientId, + height: u64, + proof: bool, +} + +impl QueryClientStateCmd { + fn validate_options( + &self, + config: &Config, + ) -> Result<(ChainConfig, QueryClientStateOptions), String> { + match (&self.chain_id, &self.client_id) { + (Some(chain_id), Some(client_id)) => { + let chain_config = config.chains.iter().find(|c| c.id == *chain_id); + + match chain_config { + Some(chain_config) => { + // check that the client_id is specified in one of the chain configurations + match config + .chains + .iter() + .find(|c| c.client_ids.contains(&client_id)) + { + Some(_) => { + let opts = QueryClientStateOptions { + client_id: client_id.parse().unwrap(), + height: match self.height { + Some(h) => h, + None => 0 as u64, + }, + proof: match self.proof { + Some(proof) => proof, + None => true, + }, + }; + Ok((chain_config.clone(), opts)) + } + None => Err(format!("cannot find client {} in config", client_id)), + } + } + None => Err(format!("cannot find chain {} in config", chain_id)), + } + } + + (None, _) => Err("missing chain identifier".to_string()), + (_, None) => Err("missing client identifier".to_string()), + } + } +} + +impl Runnable for QueryClientStateCmd { + 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 with proof: + // cargo run --bin relayer -- -c simple_config.toml query client state ibc0 ibconeclient + // this causes earlier error in ibc_query(): `.map_err(|e| error::Kind::Rpc.context(e))?;:` + // + // run without proof: + // cargo run --bin relayer -- -c simple_config.toml query client state ibc0 ibconeclient -p false + // this one fails in amino_unmarshal_binary_length_prefixed() as expected + // + let chain = TendermintChain::from_config(chain_config).unwrap(); + // To test this start a Gaia node and configure a client with the go relayer. + let _res = block_on(query_client_latest_state( + &chain, + opts.height, + opts.client_id.clone(), + opts.proof, + )) + .unwrap(); + } +} + +#[derive(Command, Debug, Options)] +pub struct QueryClientConsensusCmd { + #[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(free, help = "height of the consensus state to query")] + consensus_height: Option, + + #[options(help = "height of the consensus state to query", short = "h")] + height: Option, + + #[options(help = "whether proof is required", short = "p")] + proof: Option, +} + +#[derive(Debug)] +struct QueryClientConsensusOptions { + client_id: ClientId, + consensus_height: u64, + height: u64, + proof: bool, +} + +impl QueryClientConsensusCmd { + fn validate_options( + &self, + config: &Config, + ) -> Result<(ChainConfig, QueryClientConsensusOptions), String> { + match (&self.chain_id, &self.client_id, self.consensus_height) { + (Some(chain_id), Some(client_id), Some(consensus_height)) => { + let chain_config = config.chains.iter().find(|c| c.id == *chain_id); + + match chain_config { + Some(chain_config) => { + // check that the client_id is specified in one of the chain configurations + match config + .chains + .iter() + .find(|c| c.client_ids.contains(&client_id)) + { + Some(_) => { + let opts = QueryClientConsensusOptions { + client_id: client_id.parse().unwrap(), + consensus_height, + height: match self.height { + Some(h) => h, + None => 0 as u64, + }, + proof: match self.proof { + Some(proof) => proof, + None => true, + }, + }; + Ok((chain_config.clone(), opts)) + } + None => Err(format!("cannot find client {} in config", client_id)), + } + } + None => Err(format!("cannot find chain {} in config", chain_id)), + } + } + + (None, _, _) => Err("missing chain identifier".to_string()), + (_, None, _) => Err("missing client identifier".to_string()), + (_, _, None) => Err("missing client consensus height".to_string()), + } + } +} + +impl Runnable for QueryClientConsensusCmd { + 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 with proof: + // cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 + // this causes earlier error in ibc_query(): `.map_err(|e| error::Kind::Rpc.context(e))?;:` + // + // run without proof: + // cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 -p false + // this one fails in amino_unmarshal_binary_length_prefixed() as expected + // + let chain = TendermintChain::from_config(chain_config).unwrap(); + let _res = block_on(query_client_consensus_state( + &chain, + opts.height, + opts.client_id, + opts.consensus_height, + opts.proof, + )) + .unwrap(); + } +} + +fn block_on(future: F) -> F::Output { + Builder::new() + .basic_scheduler() + .enable_all() + .build() + .unwrap() + .block_on(future) +} diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index 5f3a3dc53f..a6402ccd54 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -77,8 +77,7 @@ impl ClientStateResponse { } None => {} } - let proof_path = - CommitmentPath::from_path(ClientStatePath::new(client_id)); + let proof_path = CommitmentPath::from_path(ClientStatePath::new(client_id)); ClientStateResponse { client_state, From 46f70ce70717ba126c40b931e37a2d0a65dbd708 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Wed, 8 Apr 2020 17:29:36 +0200 Subject: [PATCH 09/13] Try integration with tm-rs v0.33 to pick the new merkle proof --- modules/Cargo.toml | 2 +- modules/src/ics23_commitment/mod.rs | 7 ++++--- relayer/cli/Cargo.toml | 2 +- relayer/relay/Cargo.toml | 3 +-- relayer/relay/src/query/client_consensus_state.rs | 9 +-------- relayer/relay/src/query/client_state.rs | 9 +-------- 6 files changed, 9 insertions(+), 23 deletions(-) diff --git a/modules/Cargo.toml b/modules/Cargo.toml index c412becce5..b983bae85e 100644 --- a/modules/Cargo.toml +++ b/modules/Cargo.toml @@ -15,7 +15,7 @@ default = ["paths-cosmos"] paths-cosmos = [] [dependencies] -tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git" } +tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "tendermint/v0.33" } anomaly = "0.2.0" thiserror = "1.0.11" diff --git a/modules/src/ics23_commitment/mod.rs b/modules/src/ics23_commitment/mod.rs index b10701e993..92af1148a3 100644 --- a/modules/src/ics23_commitment/mod.rs +++ b/modules/src/ics23_commitment/mod.rs @@ -1,6 +1,7 @@ use serde_derive::{Deserialize, Serialize}; use crate::path::Path; +use tendermint::abci; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CommitmentRoot; @@ -17,11 +18,11 @@ impl CommitmentPath { } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct CommitmentProof; - +pub type CommitmentProof = abci::Proof; +/* impl CommitmentProof { pub fn from_bytes(_bytes: &[u8]) -> Self { todo!() } } +*/ diff --git a/relayer/cli/Cargo.toml b/relayer/cli/Cargo.toml index 902d93d3f5..82930288e6 100644 --- a/relayer/cli/Cargo.toml +++ b/relayer/cli/Cargo.toml @@ -10,7 +10,7 @@ authors = [ [dependencies] relayer = { path = "../relay" } relayer-modules = { path = "../../modules" } -tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git" } +tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "tendermint/v0.33" } anomaly = "0.2.0" gumdrop = "0.7" diff --git a/relayer/relay/Cargo.toml b/relayer/relay/Cargo.toml index bb9d1f32af..ce46d31f04 100644 --- a/relayer/relay/Cargo.toml +++ b/relayer/relay/Cargo.toml @@ -9,8 +9,7 @@ authors = [ [dependencies] relayer-modules = { path = "../../modules" } -tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git" } - +tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "tendermint/v0.33" } anomaly = "0.2.0" async-trait = "0.1.24" humantime-serde = "1.0.0" diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index 63871534d4..59db37dcde 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -77,19 +77,12 @@ impl ConsensusStateResponse { abci_proof: Option, proof_height: Height, ) -> Self { - let mut proof: CommitmentProof = CommitmentProof; - match abci_proof { - Some(abci_proof) => { - proof = CommitmentProof::from_bytes(abci_proof.as_ref()); - } - None => {} - } let proof_path = CommitmentPath::from_path(ConsensusStatePath::new(client_id, proof_height)); ConsensusStateResponse { consensus_state, - proof: Option::from(proof), + proof: abci_proof, proof_path, proof_height, } diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index a6402ccd54..85095a5629 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -70,18 +70,11 @@ impl ClientStateResponse { abci_proof: Option, proof_height: Height, ) -> Self { - let mut proof: CommitmentProof = CommitmentProof; - match abci_proof { - Some(abci_proof) => { - proof = CommitmentProof::from_bytes(abci_proof.as_ref()); - } - None => {} - } let proof_path = CommitmentPath::from_path(ClientStatePath::new(client_id)); ClientStateResponse { client_state, - proof: Option::from(proof), + proof: abci_proof, proof_path, proof_height, } From a9b9b5352caca8dd481ade7b09426e3346520fed Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 9 Apr 2020 13:16:06 +0200 Subject: [PATCH 10/13] add validation function for common params --- relayer/cli/src/commands.rs | 1 + .../cli/src/commands/query/query_client.rs | 157 ++++++++---------- relayer/cli/src/commands/start.rs | 11 +- .../relay/src/query/client_consensus_state.rs | 2 - relayer/relay/src/query/client_state.rs | 16 +- 5 files changed, 78 insertions(+), 109 deletions(-) diff --git a/relayer/cli/src/commands.rs b/relayer/cli/src/commands.rs index e4e3d3d483..808ebc9d9e 100644 --- a/relayer/cli/src/commands.rs +++ b/relayer/cli/src/commands.rs @@ -9,6 +9,7 @@ mod config; mod light; mod query; mod start; +mod utils; mod version; use self::{ diff --git a/relayer/cli/src/commands/query/query_client.rs b/relayer/cli/src/commands/query/query_client.rs index 41b7c407b2..20d03c9e3b 100644 --- a/relayer/cli/src/commands/query/query_client.rs +++ b/relayer/cli/src/commands/query/query_client.rs @@ -1,13 +1,13 @@ use crate::prelude::*; use abscissa_core::{Command, Options, Runnable}; -use core::future::Future; use relayer::config::{ChainConfig, Config}; use relayer::query::client_consensus_state::query_client_consensus_state; -use relayer::query::client_state::query_client_latest_state; +use relayer::query::client_state::query_client_full_state; + use relayer_modules::ics24_host::client::ClientId; -use tokio::runtime::Builder; +use crate::commands::utils::block_on; use relayer::chain::tendermint::TendermintChain; use tendermint::chain::Id as ChainId; @@ -38,42 +38,20 @@ impl QueryClientStateCmd { &self, config: &Config, ) -> Result<(ChainConfig, QueryClientStateOptions), String> { - match (&self.chain_id, &self.client_id) { - (Some(chain_id), Some(client_id)) => { - let chain_config = config.chains.iter().find(|c| c.id == *chain_id); - - match chain_config { - Some(chain_config) => { - // check that the client_id is specified in one of the chain configurations - match config - .chains - .iter() - .find(|c| c.client_ids.contains(&client_id)) - { - Some(_) => { - let opts = QueryClientStateOptions { - client_id: client_id.parse().unwrap(), - height: match self.height { - Some(h) => h, - None => 0 as u64, - }, - proof: match self.proof { - Some(proof) => proof, - None => true, - }, - }; - Ok((chain_config.clone(), opts)) - } - None => Err(format!("cannot find client {} in config", client_id)), - } - } - None => Err(format!("cannot find chain {} in config", chain_id)), - } - } - - (None, _) => Err("missing chain identifier".to_string()), - (_, None) => Err("missing client identifier".to_string()), - } + let (chain_config, client_id) = + validate_common_options(&self.chain_id, &self.client_id, config)?; + let opts = QueryClientStateOptions { + client_id: client_id.parse().unwrap(), + height: match self.height { + Some(h) => h, + None => 0 as u64, + }, + proof: match self.proof { + Some(proof) => proof, + None => true, + }, + }; + Ok((chain_config.clone(), opts)) } } @@ -92,15 +70,14 @@ impl Runnable for QueryClientStateCmd { // run with proof: // cargo run --bin relayer -- -c simple_config.toml query client state ibc0 ibconeclient - // this causes earlier error in ibc_query(): `.map_err(|e| error::Kind::Rpc.context(e))?;:` // // run without proof: // cargo run --bin relayer -- -c simple_config.toml query client state ibc0 ibconeclient -p false - // this one fails in amino_unmarshal_binary_length_prefixed() as expected // + // Note: currently both fail in amino_unmarshal_binary_length_prefixed(). + // To test this start a Gaia node and configure a client using the go relayer. let chain = TendermintChain::from_config(chain_config).unwrap(); - // To test this start a Gaia node and configure a client with the go relayer. - let _res = block_on(query_client_latest_state( + let _res = block_on(query_client_full_state( &chain, opts.height, opts.client_id.clone(), @@ -141,43 +118,26 @@ impl QueryClientConsensusCmd { &self, config: &Config, ) -> Result<(ChainConfig, QueryClientConsensusOptions), String> { - match (&self.chain_id, &self.client_id, self.consensus_height) { - (Some(chain_id), Some(client_id), Some(consensus_height)) => { - let chain_config = config.chains.iter().find(|c| c.id == *chain_id); - - match chain_config { - Some(chain_config) => { - // check that the client_id is specified in one of the chain configurations - match config - .chains - .iter() - .find(|c| c.client_ids.contains(&client_id)) - { - Some(_) => { - let opts = QueryClientConsensusOptions { - client_id: client_id.parse().unwrap(), - consensus_height, - height: match self.height { - Some(h) => h, - None => 0 as u64, - }, - proof: match self.proof { - Some(proof) => proof, - None => true, - }, - }; - Ok((chain_config.clone(), opts)) - } - None => Err(format!("cannot find client {} in config", client_id)), - } - } - None => Err(format!("cannot find chain {} in config", chain_id)), - } + let (chain_config, client_id) = + validate_common_options(&self.chain_id, &self.client_id, config)?; + + match self.consensus_height { + Some(consensus_height) => { + let opts = QueryClientConsensusOptions { + client_id: client_id.parse().unwrap(), + consensus_height, + height: match self.height { + Some(h) => h, + None => 0 as u64, + }, + proof: match self.proof { + Some(proof) => proof, + None => true, + }, + }; + Ok((chain_config.clone(), opts)) } - - (None, _, _) => Err("missing chain identifier".to_string()), - (_, None, _) => Err("missing client identifier".to_string()), - (_, _, None) => Err("missing client consensus height".to_string()), + None => Err("missing client consensus height".to_string()), } } } @@ -197,12 +157,12 @@ impl Runnable for QueryClientConsensusCmd { // run with proof: // cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 - // this causes earlier error in ibc_query(): `.map_err(|e| error::Kind::Rpc.context(e))?;:` // // run without proof: // cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 -p false - // this one fails in amino_unmarshal_binary_length_prefixed() as expected // + // Note: currently both fail in amino_unmarshal_binary_length_prefixed(). + // To test this start a Gaia node and configure a client using the go relayer. let chain = TendermintChain::from_config(chain_config).unwrap(); let _res = block_on(query_client_consensus_state( &chain, @@ -215,11 +175,32 @@ impl Runnable for QueryClientConsensusCmd { } } -fn block_on(future: F) -> F::Output { - Builder::new() - .basic_scheduler() - .enable_all() - .build() - .unwrap() - .block_on(future) +fn validate_common_options( + chain_id: &Option, + client_id: &Option, + config: &Config, +) -> Result<(ChainConfig, String), String> { + match (&chain_id, &client_id) { + (Some(chain_id), Some(client_id)) => { + let chain_config = config.chains.iter().find(|c| c.id == *chain_id); + + match chain_config { + Some(chain_config) => { + // check that the client_id is specified in one of the chain configurations + match config + .chains + .iter() + .find(|c| c.client_ids.contains(client_id)) + { + Some(_) => Ok((chain_config.clone(), client_id.parse().unwrap())), + None => Err(format!("cannot find client {} in config", client_id)), + } + } + None => Err(format!("cannot find chain {} in config", chain_id)), + } + } + + (None, _) => Err("missing chain identifier".to_string()), + (_, None) => Err("missing client identifier".to_string()), + } } diff --git a/relayer/cli/src/commands/start.rs b/relayer/cli/src/commands/start.rs index 275da47160..59d7b07497 100644 --- a/relayer/cli/src/commands/start.rs +++ b/relayer/cli/src/commands/start.rs @@ -1,4 +1,3 @@ -use std::future::Future; use std::time::{Duration, SystemTime}; // use crate::application::APPLICATION; @@ -9,6 +8,7 @@ use abscissa_core::{Command, Options, Runnable}; use tendermint::lite::types::Header; +use crate::commands::utils::block_on; use relayer::chain::tendermint::TendermintChain; use relayer::chain::Chain; use relayer::client::Client; @@ -98,12 +98,3 @@ async fn create_client( Client::new(chain, store, trust_options).await.unwrap() } - -fn block_on(future: F) -> F::Output { - tokio::runtime::Builder::new() - .basic_scheduler() - .enable_all() - .build() - .unwrap() - .block_on(future) -} diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index 59db37dcde..5def2e5649 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -134,8 +134,6 @@ where C: Chain, { let query = QueryClientConsensusState::new(chain_height, client_id, consensus_height, prove); - println!("XXX Query: {:?}", query.consensus_state_path.to_string()); - ibc_query(chain, query).await } diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index 85095a5629..b494c019d9 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -13,7 +13,7 @@ use super::{ibc_query, IbcQuery, IbcResponse}; use crate::chain::Chain; use crate::error; -pub struct QueryClientLatestState { +pub struct QueryClientFullState { pub chain_height: Height, pub client_id: ClientId, pub client_state_path: ClientStatePath, @@ -21,7 +21,7 @@ pub struct QueryClientLatestState { marker: PhantomData, } -impl QueryClientLatestState { +impl QueryClientFullState { pub fn new(chain_height: Height, client_id: ClientId, prove: bool) -> Self { Self { chain_height, @@ -33,7 +33,7 @@ impl QueryClientLatestState { } } -impl IbcQuery for QueryClientLatestState +impl IbcQuery for QueryClientFullState where CLS: ClientState, { @@ -81,12 +81,12 @@ impl ClientStateResponse { } } -impl IbcResponse> for ClientStateResponse +impl IbcResponse> for ClientStateResponse where CLS: ClientState, { fn from_abci_response( - query: QueryClientLatestState, + query: QueryClientFullState, response: AbciQuery, ) -> Result { match (response.value, response.proof) { @@ -105,7 +105,7 @@ where } } -pub async fn query_client_latest_state( +pub async fn query_client_full_state( chain: &C, chain_height: Height, client_id: ClientId, @@ -114,9 +114,7 @@ pub async fn query_client_latest_state( where C: Chain, { - let query = QueryClientLatestState::new(chain_height, client_id, prove); - println!("XXX Query: {:?}", query.client_state_path.to_string()); - + let query = QueryClientFullState::new(chain_height, client_id, prove); ibc_query(chain, query).await } From b1dd6eebf4efa9d930babdb955baa41162cbe615 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 9 Apr 2020 13:34:01 +0200 Subject: [PATCH 11/13] add utils --- relayer/cli/src/commands/utils.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 relayer/cli/src/commands/utils.rs diff --git a/relayer/cli/src/commands/utils.rs b/relayer/cli/src/commands/utils.rs new file mode 100644 index 0000000000..c2c0d29130 --- /dev/null +++ b/relayer/cli/src/commands/utils.rs @@ -0,0 +1,11 @@ +use core::future::Future; + +/// block on future +pub fn block_on(future: F) -> F::Output { + tokio::runtime::Builder::new() + .basic_scheduler() + .enable_all() + .build() + .unwrap() + .block_on(future) +} From b5bc8477920cc426a595cc90e4f5c858ba1bad02 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 9 Apr 2020 19:33:58 +0200 Subject: [PATCH 12/13] some cleanup and err handling --- .../cli/src/commands/query/query_client.rs | 22 ++++++++++++++----- .../relay/src/query/client_consensus_state.rs | 16 +++----------- relayer/relay/src/query/client_state.rs | 12 +++++----- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/relayer/cli/src/commands/query/query_client.rs b/relayer/cli/src/commands/query/query_client.rs index 20d03c9e3b..ad16087b96 100644 --- a/relayer/cli/src/commands/query/query_client.rs +++ b/relayer/cli/src/commands/query/query_client.rs @@ -77,13 +77,16 @@ impl Runnable for QueryClientStateCmd { // Note: currently both fail in amino_unmarshal_binary_length_prefixed(). // To test this start a Gaia node and configure a client using the go relayer. let chain = TendermintChain::from_config(chain_config).unwrap(); - let _res = block_on(query_client_full_state( + let res = block_on(query_client_full_state( &chain, opts.height, opts.client_id.clone(), opts.proof, - )) - .unwrap(); + )); + match res { + Ok(cs) => status_info!("client state query result: ", "{:?}", cs.client_state), + Err(e) => status_info!("client state query error: ", "{:?}", e), + } } } @@ -164,14 +167,21 @@ impl Runnable for QueryClientConsensusCmd { // Note: currently both fail in amino_unmarshal_binary_length_prefixed(). // To test this start a Gaia node and configure a client using the go relayer. let chain = TendermintChain::from_config(chain_config).unwrap(); - let _res = block_on(query_client_consensus_state( + let res = block_on(query_client_consensus_state( &chain, opts.height, opts.client_id, opts.consensus_height, opts.proof, - )) - .unwrap(); + )); + match res { + Ok(cs) => status_info!( + "client consensus state query result: ", + "{:?}", + cs.consensus_state + ), + Err(e) => status_info!("client consensus state query error: ", "{:?}", e), + } } } diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index 5def2e5649..4db3a3cf74 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -97,28 +97,18 @@ where query: QueryClientConsensusState, response: AbciQuery, ) -> Result { - match (response.value, response.proof) { - (Some(value), Some(proof)) => { - let consensus_state = amino_unmarshal_binary_length_prefixed(&value)?; - - Ok(ConsensusStateResponse::new( - query.client_id, - consensus_state, - Some(proof), - response.height.into(), - )) - } + match (response.value, &response.proof) { (Some(value), _) => { let consensus_state = amino_unmarshal_binary_length_prefixed(&value)?; Ok(ConsensusStateResponse::new( query.client_id, consensus_state, - None, + response.proof, response.height.into(), )) } - _ => todo!(), + (None, _) => Err(error::Kind::Rpc.context("Bad response").into()), } } } diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index b494c019d9..f3885a7530 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -89,18 +89,18 @@ where query: QueryClientFullState, response: AbciQuery, ) -> Result { - match (response.value, response.proof) { - (Some(value), Some(proof)) => { - let consensus_state = amino_unmarshal_binary_length_prefixed(&value)?; + match (response.value, &response.proof) { + (Some(value), _) => { + let client_state = amino_unmarshal_binary_length_prefixed(&value)?; Ok(ClientStateResponse::new( query.client_id, - consensus_state, - Some(proof), + client_state, + response.proof, response.height.into(), )) } - _ => todo!(), + (None, _) => Err(error::Kind::Rpc.context("Bad response").into()), } } } From b68bff6bcc84f6a531ed75020f8b9a4c6860bd9b Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 9 Apr 2020 20:06:06 +0200 Subject: [PATCH 13/13] addressing Ismail's comments --- modules/src/ics07_tendermint/client_state.rs | 2 +- .../relay/src/query/client_consensus_state.rs | 2 +- relayer/relay/src/query/client_state.rs | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/src/ics07_tendermint/client_state.rs b/modules/src/ics07_tendermint/client_state.rs index 5a5315b588..23a62474ff 100644 --- a/modules/src/ics07_tendermint/client_state.rs +++ b/modules/src/ics07_tendermint/client_state.rs @@ -12,8 +12,8 @@ pub struct ClientState { id: String, trusting_period: Duration, unbonding_period: Duration, - latest_header: Header, frozen_height: crate::Height, + latest_header: Header, } impl ClientState { diff --git a/relayer/relay/src/query/client_consensus_state.rs b/relayer/relay/src/query/client_consensus_state.rs index 4db3a3cf74..3a2a2c6ee9 100644 --- a/relayer/relay/src/query/client_consensus_state.rs +++ b/relayer/relay/src/query/client_consensus_state.rs @@ -74,7 +74,7 @@ impl ConsensusStateResponse { pub fn new( client_id: ClientId, consensus_state: CS, - abci_proof: Option, + abci_proof: Option, proof_height: Height, ) -> Self { let proof_path = diff --git a/relayer/relay/src/query/client_state.rs b/relayer/relay/src/query/client_state.rs index f3885a7530..f0f3d4b5af 100644 --- a/relayer/relay/src/query/client_state.rs +++ b/relayer/relay/src/query/client_state.rs @@ -37,7 +37,7 @@ impl IbcQuery for QueryClientFullState where CLS: ClientState, { - type Response = ClientStateResponse; + type Response = ClientFullStateResponse; fn path(&self) -> abci::Path { "/store/ibc/key".parse().unwrap() @@ -56,23 +56,23 @@ where } } -pub struct ClientStateResponse { +pub struct ClientFullStateResponse { pub client_state: CLS, pub proof: Option, pub proof_path: CommitmentPath, pub proof_height: Height, } -impl ClientStateResponse { +impl ClientFullStateResponse { pub fn new( client_id: ClientId, client_state: CLS, - abci_proof: Option, + abci_proof: Option, proof_height: Height, ) -> Self { let proof_path = CommitmentPath::from_path(ClientStatePath::new(client_id)); - ClientStateResponse { + ClientFullStateResponse { client_state, proof: abci_proof, proof_path, @@ -81,7 +81,7 @@ impl ClientStateResponse { } } -impl IbcResponse> for ClientStateResponse +impl IbcResponse> for ClientFullStateResponse where CLS: ClientState, { @@ -93,7 +93,7 @@ where (Some(value), _) => { let client_state = amino_unmarshal_binary_length_prefixed(&value)?; - Ok(ClientStateResponse::new( + Ok(ClientFullStateResponse::new( query.client_id, client_state, response.proof, @@ -110,7 +110,7 @@ pub async fn query_client_full_state( chain_height: Height, client_id: ClientId, prove: bool, -) -> Result, error::Error> +) -> Result, error::Error> where C: Chain, {