From 1efdfdeade79235a45ca356854f035b35286268d Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Wed, 16 Sep 2020 17:18:57 +0200 Subject: [PATCH 1/4] Adapted client query subcommands to new query infrastructure (does not compile yet). --- modules/src/ics24_host/path.rs | 4 +- modules/src/mock_client/client_def.rs | 2 +- relayer-cli/src/commands/query.rs | 1 - relayer-cli/src/commands/query/client.rs | 75 ++++++++++-------------- relayer/src/chain/cosmos.rs | 9 ++- relayer/src/error.rs | 8 +-- relayer/src/query/client.rs | 60 ------------------- 7 files changed, 44 insertions(+), 115 deletions(-) delete mode 100644 relayer/src/query/client.rs diff --git a/modules/src/ics24_host/path.rs b/modules/src/ics24_host/path.rs index 456bbbf75b..2579bd1f7e 100644 --- a/modules/src/ics24_host/path.rs +++ b/modules/src/ics24_host/path.rs @@ -11,7 +11,7 @@ pub const IBC_QUERY_PATH: &str = "store/ibc/key"; pub enum Path { ClientType(ClientId), ClientState(ClientId), - ConsensusState(ClientId, u64), + ClientConsensusState(ClientId, u64), ClientConnections(ClientId), Connections(ConnectionId), Ports(PortId), @@ -47,7 +47,7 @@ impl Display for Path { match &self { Path::ClientType(id) => write!(f, "clients/{}/clientType", id), Path::ClientState(id) => write!(f, "clients/{}/clientState", id), - Path::ConsensusState(id, height) => { + Path::ClientConsensusState(id, height) => { write!(f, "clients/{}/consensusState/{}", id, height) } Path::ClientConnections(id) => write!(f, "clients/{}/connections", id), diff --git a/modules/src/mock_client/client_def.rs b/modules/src/mock_client/client_def.rs index 2208fcddf1..146ec1e45f 100644 --- a/modules/src/mock_client/client_def.rs +++ b/modules/src/mock_client/client_def.rs @@ -40,7 +40,7 @@ impl ClientDef for MockClient { _expected_consensus_state: &Self::ConsensusState, ) -> Result<(), Box> { let client_prefixed_path = - Path::ConsensusState(client_id.clone(), height.value()).to_string(); + Path::ClientConsensusState(client_id.clone(), height.value()).to_string(); let _path = apply_prefix(prefix, client_prefixed_path)?; diff --git a/relayer-cli/src/commands/query.rs b/relayer-cli/src/commands/query.rs index 4e236bb9e6..9157ab7ef9 100644 --- a/relayer-cli/src/commands/query.rs +++ b/relayer-cli/src/commands/query.rs @@ -27,7 +27,6 @@ pub enum QueryClientCmds { /// The `query client state` subcommand #[options(help = "query client full state")] State(client::QueryClientStateCmd), - /// The `query client consensus` subcommand /// The `query client consensus` subcommand #[options(help = "query client consensus")] diff --git a/relayer-cli/src/commands/query/client.rs b/relayer-cli/src/commands/query/client.rs index 80aee8facc..66965d0ab4 100644 --- a/relayer-cli/src/commands/query/client.rs +++ b/relayer-cli/src/commands/query/client.rs @@ -5,10 +5,12 @@ use relayer::config::{ChainConfig, Config}; use ibc::ics24_host::error::ValidationError; use ibc::ics24_host::identifier::{ClientId, ConnectionId}; -use ibc::ics24_host::Path::ClientConnections; +use ibc::ics24_host::Path::{ClientConnections, ClientState, ClientConsensusState}; use relayer::chain::Chain; use relayer::chain::CosmosSDKChain; use tendermint::chain::Id as ChainId; +use ibc::ics02_client::client_def::{AnyClientState, AnyConsensusState}; + /// Query client state command #[derive(Clone, Command, Debug, Options)] @@ -19,7 +21,7 @@ pub struct QueryClientStateCmd { #[options(free, help = "identifier of the client to query")] client_id: Option, - #[options(help = "height of the state to query", short = "h")] + #[options(help = "the chain height which this query should reflect", short = "h")] height: Option, #[options(help = "whether proof is required", short = "p")] @@ -56,6 +58,12 @@ impl QueryClientStateCmd { } } +/// Command for handling a query for a client's state. +/// To run with proof: +/// cargo run --bin relayer -- -c relayer/tests/config/fixtures/simple_config.toml query client state ibc-test ethbridge --height 3 +/// +/// Run without proof: +/// cargo run --bin relayer -- -c relayer/tests/config/fixtures/simple_config.toml query client state ibc-test ethbridge --height 3 -p false impl Runnable for QueryClientStateCmd { fn run(&self) { let config = app_config(); @@ -69,27 +77,16 @@ impl Runnable for QueryClientStateCmd { }; status_info!("Options", "{:?}", opts); - // run with proof: - // cargo run --bin relayer -- -c relayer/tests/config/fixtures/simple_config.toml query client state ibc-test ethbridge --height 3 - // - // run without proof: - // cargo run --bin relayer -- -c relayer/tests/config/fixtures/simple_config.toml query client state ibc-test ethbridge --height 3 -p false - // - // 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 = CosmosSDKChain::from_config(chain_config).unwrap(); - /* Todo: Implement client full state query - let res = block_on(query_client_full_state( - &chain, + let chain = CosmosSDKChain::from_config(chain_config).unwrap(); + let res = chain.query::( + ClientState(opts.client_id), opts.height, - opts.client_id.clone(), - opts.proof, - )); + opts.proof + ); match res { - Ok(cs) => status_info!("client state query result: ", "{:?}", cs.client_state), + Ok(cs) => status_info!("client state query result: ", "{:?}", cs), Err(e) => status_info!("client state query error: ", "{:?}", e), } - */ } } @@ -102,10 +99,10 @@ pub struct QueryClientConsensusCmd { #[options(free, help = "identifier of the client to query")] client_id: Option, - #[options(free, help = "height of the consensus state to query")] + #[options(free, help = "height of the client's consensus state to query")] consensus_height: Option, - #[options(help = "height of the consensus state to query", short = "h")] + #[options(help = "the chain height which this query should reflect", short = "h")] height: Option, #[options(help = "whether proof is required", short = "p")] @@ -149,6 +146,13 @@ impl QueryClientConsensusCmd { } } + +/// Implementation of the query for a client's consensus state at a certain height. +/// Run with proof: +/// cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 +/// +/// Run without proof: +/// cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 -p false impl Runnable for QueryClientConsensusCmd { fn run(&self) { let config = app_config(); @@ -162,33 +166,16 @@ impl Runnable for QueryClientConsensusCmd { }; status_info!("Options", "{:?}", opts); - // run with proof: - // cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 - // - // run without proof: - // cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 -p false - // - // 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 = CosmosSDKChain::from_config(chain_config).unwrap(); - /* Todo: Implement client consensus state query - let res = block_on(query_client_consensus_state( - &chain, + let chain = CosmosSDKChain::from_config(chain_config).unwrap(); + let res = chain.query::( + ClientConsensusState(opts.client_id, opts.consensus_height), opts.height, - opts.client_id, - opts.consensus_height, opts.proof, - )); + ); match res { - Ok(cs) => status_info!( - "client consensus state query result: ", - "{:?}", - cs.consensus_state - ), + Ok(cs) => status_info!("client consensus state query result: ", "{:?}", cs), Err(e) => status_info!("client consensus state query error: ", "{:?}", e), } - - */ } } @@ -222,7 +209,7 @@ pub struct QueryClientConnectionsCmd { #[options(free, help = "identifier of the client to query")] client_id: Option, - #[options(help = "height of the state to query", short = "h")] + #[options(help = "the chain height which this query should reflect", short = "h")] height: Option, #[options(help = "whether proof is required", short = "p")] diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index fd6fa1c87c..ca53d70d45 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -46,8 +46,8 @@ impl Chain for CosmosSDKChain { type Header = TMHeader; type Commit = TMCommit; type ConsensusState = ConsensusState; - type Requester = RpcRequester; type ClientState = ClientState; + type Requester = RpcRequester; type Error = anomaly::Error; fn query(&self, data: Path, height: u64, prove: bool) -> Result @@ -57,7 +57,7 @@ impl Chain for CosmosSDKChain { let path = TendermintABCIPath::from_str(IBC_QUERY_PATH).unwrap(); if !data.is_provable() & prove { return Err(Kind::Store - .context("requested proof for privateStore path") + .context("requested proof for a path in the privateStore") .into()); } let response = block_on(abci_query(&self, path, data.to_string(), height, prove))?; @@ -67,7 +67,10 @@ impl Chain for CosmosSDKChain { dbg!("Todo: implement proof verification."); // Todo: Verify proof } - // Deserialize response data. + // Deserialize response data. This involves two steps: (1) `decode` from the wire bytes into + // a Prost type (such as `ibc_proto::channel::Channel`) called intuitively a raw type; + // and (2) then translate with `try_from` from the Prost raw type into an actual domain type + // (e.g., `ibc::ics04_channel::channel::ChannelEnd`). T::RawType::decode(Bytes::from(response)) .map_err(|e| Kind::ResponseParsing.context(e).into()) .and_then(|r| T::try_from(r).map_err(|e| Kind::ResponseParsing.context(e).into())) diff --git a/relayer/src/error.rs b/relayer/src/error.rs index 0028743b13..1f3ac6a191 100644 --- a/relayer/src/error.rs +++ b/relayer/src/error.rs @@ -14,19 +14,19 @@ pub enum Kind { ConfigIo, /// Invalid configuration - #[error("invalid configuration")] + #[error("Invalid configuration")] Config, - /// RPC error (typcally raised by the RPC client or the RPC requester) + /// RPC error (typically raised by the RPC client or the RPC requester) #[error("RPC error")] Rpc, /// Light client error, typically raised by a `Client` - #[error("light client error")] + #[error("Light client error")] LightClient, /// Trusted store error, raised by instances of `Store` - #[error("store error")] + #[error("Store error")] Store, /// Event error (raised by the event monitor) diff --git a/relayer/src/query/client.rs b/relayer/src/query/client.rs deleted file mode 100644 index 4ee341fa2d..0000000000 --- a/relayer/src/query/client.rs +++ /dev/null @@ -1,60 +0,0 @@ -use modules::ics24_host::identifier::ClientId; -use modules::Height; - -use crate::chain::Chain; -use modules::ics02_client::query::{ClientFullStateResponse, ConsensusStateResponse}; - -use modules::error; - -pub async fn query_client_full_state( - _chain: &C, - _chain_height: Height, - _client_id: ClientId, - _prove: bool, -) -> Result, error::Error> -where - C: Chain, -{ - todo!("Implement generic query for client") - /* - let _query = QueryClientFullState::new(chain_height, client_id, prove); - ibc_query( - chain, - Request { - path: None, - data: vec![], - height: Some(TendermintHeight::from(chain_height)), - prove, - }, - query, - ) - .await - */ -} - -pub async fn query_client_consensus_state( - _chain: &C, - _chain_height: Height, - _client_id: ClientId, - _consensus_height: Height, - _prove: bool, -) -> Result, error::Error> -where - C: Chain, -{ - todo!("Implement generic query for client") - /* - let _query = QueryClientConsensusState::new(chain_height, client_id, consensus_height, prove); - ibc_query( - chain, - Request { - path: None, - data: vec![], - height: Some(TendermintHeight::from(chain_height)), - prove, - }, - query, - ) - .await - */ -} From 8a82a6e3564f5c8bfbd52b24e8f55c542fd494ef Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Thu, 17 Sep 2020 16:48:21 +0200 Subject: [PATCH 2/4] Fixes for ClientState -> AnyClientState --- modules/src/ics02_client/client_def.rs | 27 +++++++++++--------- modules/src/ics03_connection/msgs.rs | 6 ++--- modules/src/ics07_tendermint/client_state.rs | 2 +- modules/src/mock_client/state.rs | 2 +- relayer-cli/src/commands/query/client.rs | 20 +++++++-------- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index b6d4aa3d59..4fa2964c42 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -119,11 +119,14 @@ pub enum AnyClientState { Mock(MockClientState), } -impl AnyClientState { - pub fn from_any(any: prost_types::Any) -> Result { - match any.type_url.as_str() { +impl TryFromRaw for AnyClientState { + type RawType = prost_types::Any; + type Error = Error; + + fn try_from(value: Self::RawType) -> Result { + match value.type_url.as_str() { "ibc.tendermint.ClientState" => { - let raw = RawTendermintClientState::decode(any.value.as_ref()) + let raw = RawTendermintClientState::decode(value.value.as_ref()) .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; let client_state = TendermintClientState::try_from(raw) .map_err(|e| error::Kind::InvalidRawClientState.context(e))?; @@ -133,7 +136,7 @@ impl AnyClientState { #[cfg(test)] "ibc.mock.ClientState" => { - let raw = RawMockClientState::decode(any.value.as_ref()) + let raw = RawMockClientState::decode(value.value.as_ref()) .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; let client_state = MockClientState::try_from(raw) .map_err(|e| error::Kind::InvalidRawClientState.context(e))?; @@ -141,7 +144,7 @@ impl AnyClientState { Ok(AnyClientState::Mock(client_state)) } - _ => Err(error::Kind::UnknownClientStateType(any.type_url).into()), + _ => Err(error::Kind::UnknownClientStateType(value.type_url).into()), } } } @@ -160,21 +163,21 @@ impl ClientState for AnyClientState { } } - fn is_frozen(&self) -> bool { + fn latest_height(&self) -> Height { match self { - AnyClientState::Tendermint(tm_state) => tm_state.is_frozen(), + Self::Tendermint(tm_state) => tm_state.latest_height(), #[cfg(test)] - AnyClientState::Mock(mock_state) => mock_state.is_frozen(), + Self::Mock(mock_state) => mock_state.latest_height(), } } - fn latest_height(&self) -> Height { + fn is_frozen(&self) -> bool { match self { - Self::Tendermint(tm_state) => tm_state.latest_height(), + AnyClientState::Tendermint(tm_state) => tm_state.is_frozen(), #[cfg(test)] - Self::Mock(mock_state) => mock_state.latest_height(), + AnyClientState::Mock(mock_state) => mock_state.is_frozen(), } } } diff --git a/modules/src/ics03_connection/msgs.rs b/modules/src/ics03_connection/msgs.rs index 569d4217bb..21585d3e04 100644 --- a/modules/src/ics03_connection/msgs.rs +++ b/modules/src/ics03_connection/msgs.rs @@ -218,8 +218,8 @@ impl Msg for MsgConnectionOpenTry { } impl TryFromRaw for MsgConnectionOpenTry { - type Error = Error; type RawType = RawMsgConnectionOpenTry; + type Error = Error; fn try_from(msg: RawMsgConnectionOpenTry) -> Result { let proof_height = msg @@ -249,7 +249,7 @@ impl TryFromRaw for MsgConnectionOpenTry { .map_err(|e| Kind::IdentifierError.context(e))?, client_state: msg .client_state - .map(AnyClientState::from_any) + .map(AnyClientState::try_from) .transpose() .map_err(|e| Kind::InvalidProof.context(e))?, counterparty: msg @@ -368,7 +368,7 @@ impl TryFromRaw for MsgConnectionOpenAck { .map_err(|e| Kind::IdentifierError.context(e))?, client_state: msg .client_state - .map(AnyClientState::from_any) + .map(AnyClientState::try_from) .transpose() .map_err(|e| Kind::InvalidProof.context(e))?, version: validate_version(msg.version).map_err(|e| Kind::InvalidVersion.context(e))?, diff --git a/modules/src/ics07_tendermint/client_state.rs b/modules/src/ics07_tendermint/client_state.rs index fa83165efd..c87c3df9c2 100644 --- a/modules/src/ics07_tendermint/client_state.rs +++ b/modules/src/ics07_tendermint/client_state.rs @@ -92,8 +92,8 @@ impl crate::ics02_client::state::ClientState for ClientState { } impl TryFromRaw for ClientState { - type Error = Error; type RawType = ibc_proto::ibc::tendermint::ClientState; + type Error = Error; fn try_from(raw: Self::RawType) -> Result { Ok(Self { diff --git a/modules/src/mock_client/state.rs b/modules/src/mock_client/state.rs index 28c5be8303..c1a7eb3992 100644 --- a/modules/src/mock_client/state.rs +++ b/modules/src/mock_client/state.rs @@ -62,8 +62,8 @@ impl From for AnyClientState { } impl TryFromRaw for MockClientState { - type Error = Error; type RawType = ibc_proto::ibc::mock::ClientState; + type Error = Error; fn try_from(raw: Self::RawType) -> Result { let raw_header = raw diff --git a/relayer-cli/src/commands/query/client.rs b/relayer-cli/src/commands/query/client.rs index 66965d0ab4..9278f38328 100644 --- a/relayer-cli/src/commands/query/client.rs +++ b/relayer-cli/src/commands/query/client.rs @@ -166,16 +166,16 @@ impl Runnable for QueryClientConsensusCmd { }; status_info!("Options", "{:?}", opts); - let chain = CosmosSDKChain::from_config(chain_config).unwrap(); - let res = chain.query::( - ClientConsensusState(opts.client_id, opts.consensus_height), - opts.height, - opts.proof, - ); - match res { - Ok(cs) => status_info!("client consensus state query result: ", "{:?}", cs), - Err(e) => status_info!("client consensus state query error: ", "{:?}", e), - } + let _chain = CosmosSDKChain::from_config(chain_config).unwrap(); + // let res = chain.query::( + // ClientConsensusState(opts.client_id, opts.consensus_height), + // opts.height, + // opts.proof, + // ); + // match res { + // Ok(cs) => status_info!("client consensus state query result: ", "{:?}", cs), + // Err(e) => status_info!("client consensus state query error: ", "{:?}", e), + // } } } From 106c459cab6cc1a6359759c7bfc2d0d62e004686 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Thu, 17 Sep 2020 17:35:40 +0200 Subject: [PATCH 3/4] Fix for ConsensusState -> AnyConsensusState up to deserialization. --- modules/src/ics02_client/client_def.rs | 35 ++++++++++++++++++- modules/src/ics02_client/error.rs | 6 ++++ .../src/ics07_tendermint/consensus_state.rs | 11 ++++++ relayer-cli/src/commands/query/client.rs | 33 ++++++++--------- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index 4fa2964c42..1552d86f86 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -10,11 +10,14 @@ use crate::ics03_connection::connection::ConnectionEnd; use crate::ics07_tendermint as tendermint; use crate::ics07_tendermint::client_def::TendermintClient; use crate::ics07_tendermint::client_state::ClientState as TendermintClientState; +use crate::ics07_tendermint::consensus_state::ConsensusState as TendermintConsensusState; use crate::ics23_commitment::commitment::{CommitmentPrefix, CommitmentProof, CommitmentRoot}; use crate::ics24_host::identifier::{ClientId, ConnectionId}; use crate::try_from_raw::TryFromRaw; -use ibc_proto::ibc::tendermint::ClientState as RawTendermintClientState; +use ibc_proto::ibc::tendermint::{ + ClientState as RawTendermintClientState, ConsensusState as RawTendermintConsensusState, +}; use ::tendermint::block::Height; @@ -190,6 +193,36 @@ pub enum AnyConsensusState { Mock(MockConsensusState), } +impl TryFromRaw for AnyConsensusState { + type RawType = prost_types::Any; + type Error = Error; + + fn try_from(value: Self::RawType) -> Result { + match value.type_url.as_str() { + "ibc.tendermint.ConsensusState" => { + let raw = RawTendermintConsensusState::decode(value.value.as_ref()) + .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; + let consensus_state = TendermintConsensusState::try_from(raw) + .map_err(|e| error::Kind::InvalidRawConsensusState.context(e))?; + + Ok(AnyConsensusState::Tendermint(consensus_state)) + } + + // TODO get this to compile! -- Add the ClientConsensusState definition in ibc-proto. + // #[cfg(test)] + // "ibc.mock.ConsensusState" => { + // let raw = RawMockConsensusState::decode(value.value.as_ref()) + // .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; + // let client_state = MockClientState::try_from(raw) + // .map_err(|e| error::Kind::InvalidRawClientState.context(e))?; + // + // Ok(AnyClientState::Mock(client_state)) + // } + _ => Err(error::Kind::UnknownConsensusStateType(value.type_url).into()), + } + } +} + impl ConsensusState for AnyConsensusState { fn client_type(&self) -> ClientType { todo!() diff --git a/modules/src/ics02_client/error.rs b/modules/src/ics02_client/error.rs index f6f19ffe23..3be580296f 100644 --- a/modules/src/ics02_client/error.rs +++ b/modules/src/ics02_client/error.rs @@ -31,9 +31,15 @@ pub enum Kind { #[error("unknown client state type: {0}")] UnknownClientStateType(String), + #[error("unknown client consensus state type: {0}")] + UnknownConsensusStateType(String), + #[error("invalid raw client state")] InvalidRawClientState, + #[error("invalid raw client consensus state")] + InvalidRawConsensusState, + #[error("invalid raw header")] InvalidRawHeader, diff --git a/modules/src/ics07_tendermint/consensus_state.rs b/modules/src/ics07_tendermint/consensus_state.rs index c6a9f9ea24..31e345e475 100644 --- a/modules/src/ics07_tendermint/consensus_state.rs +++ b/modules/src/ics07_tendermint/consensus_state.rs @@ -1,6 +1,8 @@ use crate::ics02_client::client_type::ClientType; use crate::ics23_commitment::commitment::CommitmentRoot; +use crate::ics07_tendermint::error::Error; +use crate::try_from_raw::TryFromRaw; use serde_derive::{Deserialize, Serialize}; use tendermint::Hash; @@ -12,6 +14,15 @@ pub struct ConsensusState { pub next_validators_hash: Hash, } +impl TryFromRaw for ConsensusState { + type RawType = ibc_proto::ibc::tendermint::ConsensusState; + type Error = Error; + + fn try_from(_raw: Self::RawType) -> Result { + unimplemented!() + } +} + impl ConsensusState { pub fn new( root: CommitmentRoot, diff --git a/relayer-cli/src/commands/query/client.rs b/relayer-cli/src/commands/query/client.rs index 9278f38328..db28506534 100644 --- a/relayer-cli/src/commands/query/client.rs +++ b/relayer-cli/src/commands/query/client.rs @@ -3,14 +3,13 @@ use crate::prelude::*; use abscissa_core::{Command, Options, Runnable}; use relayer::config::{ChainConfig, Config}; +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, ClientState, ClientConsensusState}; +use ibc::ics24_host::Path::{ClientConnections, ClientConsensusState, ClientState}; use relayer::chain::Chain; use relayer::chain::CosmosSDKChain; use tendermint::chain::Id as ChainId; -use ibc::ics02_client::client_def::{AnyClientState, AnyConsensusState}; - /// Query client state command #[derive(Clone, Command, Debug, Options)] @@ -78,11 +77,8 @@ impl Runnable for QueryClientStateCmd { status_info!("Options", "{:?}", opts); let chain = CosmosSDKChain::from_config(chain_config).unwrap(); - let res = chain.query::( - ClientState(opts.client_id), - opts.height, - opts.proof - ); + let res = + chain.query::(ClientState(opts.client_id), opts.height, opts.proof); match res { Ok(cs) => status_info!("client state query result: ", "{:?}", cs), Err(e) => status_info!("client state query error: ", "{:?}", e), @@ -146,7 +142,6 @@ impl QueryClientConsensusCmd { } } - /// Implementation of the query for a client's consensus state at a certain height. /// Run with proof: /// cargo run --bin relayer -- -c simple_config.toml query client consensus ibc0 ibconeclient 22 @@ -166,16 +161,16 @@ impl Runnable for QueryClientConsensusCmd { }; status_info!("Options", "{:?}", opts); - let _chain = CosmosSDKChain::from_config(chain_config).unwrap(); - // let res = chain.query::( - // ClientConsensusState(opts.client_id, opts.consensus_height), - // opts.height, - // opts.proof, - // ); - // match res { - // Ok(cs) => status_info!("client consensus state query result: ", "{:?}", cs), - // Err(e) => status_info!("client consensus state query error: ", "{:?}", e), - // } + let chain = CosmosSDKChain::from_config(chain_config).unwrap(); + let res = chain.query::( + ClientConsensusState(opts.client_id, opts.consensus_height), + opts.height, + opts.proof, + ); + match res { + Ok(cs) => status_info!("client consensus state query result: ", "{:?}", cs), + Err(e) => status_info!("client consensus state query error: ", "{:?}", e), + } } } From 194b5009d31676e4a8bba13eb1bde9cceae17262 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Fri, 18 Sep 2020 12:29:21 +0200 Subject: [PATCH 4/4] Added impl TryFromRaw for AnyClientState; fixes for Anca's review --- modules/Cargo.toml | 1 + modules/src/ics02_client/client_def.rs | 19 ++++++------ .../src/ics07_tendermint/consensus_state.rs | 30 +++++++++++++++++-- modules/src/ics07_tendermint/error.rs | 3 ++ modules/src/ics23_commitment/commitment.rs | 15 +++++++--- modules/src/ics24_host/path.rs | 1 - 6 files changed, 52 insertions(+), 17 deletions(-) diff --git a/modules/Cargo.toml b/modules/Cargo.toml index 7445e05f5f..c8c428afff 100644 --- a/modules/Cargo.toml +++ b/modules/Cargo.toml @@ -22,6 +22,7 @@ tendermint-rpc = { version = "0.15.0", features = ["client"] } ibc-proto = "0.3.0" anomaly = "0.2.0" +chrono = "0.4" thiserror = "1.0.11" serde_derive = "1.0.104" serde = "1.0.104" diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index 1552d86f86..44ba5e5215 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -126,10 +126,11 @@ impl TryFromRaw for AnyClientState { type RawType = prost_types::Any; type Error = Error; - fn try_from(value: Self::RawType) -> Result { - match value.type_url.as_str() { - "ibc.tendermint.ClientState" => { - let raw = RawTendermintClientState::decode(value.value.as_ref()) + // TODO Fix type urls: avoid having hardcoded values sprinkled around the whole codebase. + fn try_from(raw: Self::RawType) -> Result { + match raw.type_url.as_str() { + "/ibc.tendermint.ClientState" => { + let raw = RawTendermintClientState::decode(raw.value.as_ref()) .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; let client_state = TendermintClientState::try_from(raw) .map_err(|e| error::Kind::InvalidRawClientState.context(e))?; @@ -138,8 +139,8 @@ impl TryFromRaw for AnyClientState { } #[cfg(test)] - "ibc.mock.ClientState" => { - let raw = RawMockClientState::decode(value.value.as_ref()) + "/ibc.mock.ClientState" => { + let raw = RawMockClientState::decode(raw.value.as_ref()) .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; let client_state = MockClientState::try_from(raw) .map_err(|e| error::Kind::InvalidRawClientState.context(e))?; @@ -147,7 +148,7 @@ impl TryFromRaw for AnyClientState { Ok(AnyClientState::Mock(client_state)) } - _ => Err(error::Kind::UnknownClientStateType(value.type_url).into()), + _ => Err(error::Kind::UnknownClientStateType(raw.type_url).into()), } } } @@ -199,7 +200,7 @@ impl TryFromRaw for AnyConsensusState { fn try_from(value: Self::RawType) -> Result { match value.type_url.as_str() { - "ibc.tendermint.ConsensusState" => { + "/ibc.tendermint.ConsensusState" => { let raw = RawTendermintConsensusState::decode(value.value.as_ref()) .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; let consensus_state = TendermintConsensusState::try_from(raw) @@ -210,7 +211,7 @@ impl TryFromRaw for AnyConsensusState { // TODO get this to compile! -- Add the ClientConsensusState definition in ibc-proto. // #[cfg(test)] - // "ibc.mock.ConsensusState" => { + // "/ibc.mock.ConsensusState" => { // let raw = RawMockConsensusState::decode(value.value.as_ref()) // .map_err(|e| error::Kind::ProtoDecodingFailure.context(e))?; // let client_state = MockClientState::try_from(raw) diff --git a/modules/src/ics07_tendermint/consensus_state.rs b/modules/src/ics07_tendermint/consensus_state.rs index 31e345e475..623800c6be 100644 --- a/modules/src/ics07_tendermint/consensus_state.rs +++ b/modules/src/ics07_tendermint/consensus_state.rs @@ -1,9 +1,11 @@ use crate::ics02_client::client_type::ClientType; use crate::ics23_commitment::commitment::CommitmentRoot; -use crate::ics07_tendermint::error::Error; +use crate::ics07_tendermint::error::{Error, Kind}; use crate::try_from_raw::TryFromRaw; +use chrono::{TimeZone, Utc}; use serde_derive::{Deserialize, Serialize}; +use tendermint::hash::Algorithm; use tendermint::Hash; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -18,8 +20,30 @@ impl TryFromRaw for ConsensusState { type RawType = ibc_proto::ibc::tendermint::ConsensusState; type Error = Error; - fn try_from(_raw: Self::RawType) -> Result { - unimplemented!() + // TODO: Fix height conversion below (which ignores epoch number, hence it's incorrect). + // Related: https://github.com/informalsystems/ibc-rs/issues/191. + fn try_from(raw: Self::RawType) -> Result { + let proto_timestamp = raw + .timestamp + .ok_or_else(|| Kind::InvalidRawConsensusState.context("missing timestamp"))?; + + Ok(Self { + root: raw + .root + .ok_or_else(|| Kind::InvalidRawConsensusState.context("missing commitment root"))? + .hash + .into(), + height: raw + .height + .ok_or_else(|| Kind::InvalidRawConsensusState.context("missing height"))? + .epoch_height + .into(), + timestamp: Utc + .timestamp(proto_timestamp.seconds, proto_timestamp.nanos as u32) + .into(), + next_validators_hash: Hash::new(Algorithm::Sha256, &raw.next_validators_hash) + .map_err(|e| Kind::InvalidRawConsensusState.context(e.to_string()))?, + }) } } diff --git a/modules/src/ics07_tendermint/error.rs b/modules/src/ics07_tendermint/error.rs index af9e13cf10..c7b633d66e 100644 --- a/modules/src/ics07_tendermint/error.rs +++ b/modules/src/ics07_tendermint/error.rs @@ -22,6 +22,9 @@ pub enum Kind { #[error("invalid raw client state")] InvalidRawClientState, + + #[error("invalid raw client consensus state")] + InvalidRawConsensusState, } impl Kind { diff --git a/modules/src/ics23_commitment/commitment.rs b/modules/src/ics23_commitment/commitment.rs index bcf3e134bd..68edfdc77a 100644 --- a/modules/src/ics23_commitment/commitment.rs +++ b/modules/src/ics23_commitment/commitment.rs @@ -3,11 +3,18 @@ use serde_derive::{Deserialize, Serialize}; use std::fmt; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct CommitmentRoot; +pub struct CommitmentRoot(Vec); impl CommitmentRoot { - pub fn from_bytes(_bytes: &[u8]) -> Self { - // TODO - CommitmentRoot {} + pub fn from_bytes(bytes: &[u8]) -> Self { + Self { + 0: Vec::from(bytes), + } + } +} + +impl From> for CommitmentRoot { + fn from(v: Vec) -> Self { + Self { 0: v } } } diff --git a/modules/src/ics24_host/path.rs b/modules/src/ics24_host/path.rs index 2579bd1f7e..62a485f403 100644 --- a/modules/src/ics24_host/path.rs +++ b/modules/src/ics24_host/path.rs @@ -27,7 +27,6 @@ impl Path { /// Indication if the path is provable. pub fn is_provable(&self) -> bool { match &self { - Path::ClientState(_) => false, Path::ClientConnections(_) => false, Path::Ports(_) => false, _ => true,