From 93f8487636d2087e8335a978f5ec0cd9b2b8bf18 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Wed, 14 Oct 2020 13:10:50 +0200 Subject: [PATCH 1/5] fix type-urls, introduce constants --- modules/src/ics02_client/client_def.rs | 35 +++++++++++++------------- modules/src/ics02_client/msgs.rs | 2 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index ffb8971ac8..7dbc97d5c2 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -18,6 +18,12 @@ use crate::Height; use tendermint_proto::{DomainType, Error, Kind}; +pub const TENDERMINT_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.ClientState"; +pub const TENDERMINT_CONSENSUS_STATE_TYPE_URL: &str = + "/ibc.lightclients.tendermint.v1.ConsensusState"; +pub const MOCK_CLIENT_STATE_TYPE_URL: &str = "/ibc.mock.ClientState"; +pub const MOCK_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.mock.ConsensusState"; + #[cfg(test)] use { crate::mock_client::client_def::MockClient, @@ -137,12 +143,12 @@ impl TryFrom for AnyClientState { // TODO Fix type urls: avoid having hardcoded values sprinkled around the whole codebase. fn try_from(raw: Any) -> Result { match raw.type_url.as_str() { - "/ibc.tendermint.ClientState" => Ok(AnyClientState::Tendermint( + TENDERMINT_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Tendermint( TendermintClientState::decode_vec(&raw.value)?, )), #[cfg(test)] - "/ibc.mock.ClientState" => Ok(AnyClientState::Mock(MockClientState::decode_vec( + MOCK_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Mock(MockClientState::decode_vec( &raw.value, )?)), @@ -157,12 +163,12 @@ impl From for Any { fn from(value: AnyClientState) -> Self { match value { AnyClientState::Tendermint(value) => Any { - type_url: "/ibc.tendermint.ClientState".to_string(), + type_url: TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), value: value.encode_vec().unwrap(), }, #[cfg(test)] AnyClientState::Mock(value) => Any { - type_url: "/ibc.mock.ClientState".to_string(), + type_url: MOCK_CLIENT_STATE_TYPE_URL.to_string(), value: value.encode_vec().unwrap(), }, } @@ -217,20 +223,15 @@ impl TryFrom for AnyConsensusState { fn try_from(value: Any) -> Result { match value.type_url.as_str() { - "/ibc.tendermint.ConsensusState" => Ok(AnyConsensusState::Tendermint( + TENDERMINT_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Tendermint( TendermintConsensusState::decode_vec(&value.value)?, )), - // 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)) - // } + #[cfg(test)] + MOCK_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Mock( + MockConsensusState::decode_vec(&value.value)?, + )), + _ => Err(Kind::DecodeMessage .context(error::Kind::UnknownConsensusStateType(value.type_url)) .into()), @@ -242,12 +243,12 @@ impl From for Any { fn from(value: AnyConsensusState) -> Self { match value { AnyConsensusState::Tendermint(value) => Any { - type_url: "/ibc.tendermint.ConsensusState".to_string(), + type_url: TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(), value: value.encode_vec().unwrap(), }, #[cfg(test)] AnyConsensusState::Mock(value) => Any { - type_url: "/ibc.mock.ConsensusState".to_string(), + type_url: MOCK_CONSENSUS_STATE_TYPE_URL.to_string(), value: value.encode_vec().unwrap(), }, } diff --git a/modules/src/ics02_client/msgs.rs b/modules/src/ics02_client/msgs.rs index ee62ac1e6b..26d7ec530e 100644 --- a/modules/src/ics02_client/msgs.rs +++ b/modules/src/ics02_client/msgs.rs @@ -92,7 +92,7 @@ impl TryFrom for MsgCreateAnyClient { .ok_or_else(|| Kind::DecodeMessage.context(error::Kind::InvalidRawClientState))?; let client_type = match raw_client_state.type_url.as_str() { - "/ibc.tendermint.ClientState" => Ok(ClientType::Tendermint), + "/ibc.lightclients.tendermint.v1.ClientState" => Ok(ClientType::Tendermint), _ => Err( Kind::DecodeMessage.context(error::Kind::UnknownConsensusStateType( From 7037a0a465cd1401ce5693fa30f3ba30057368b5 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Wed, 14 Oct 2020 17:32:58 +0200 Subject: [PATCH 2/5] Remove client_type from MsgCreateAnyClient, initial cleanup of tests and mock context --- modules/src/ics02_client/client_def.rs | 19 +++ modules/src/ics02_client/context.rs | 7 - modules/src/ics02_client/context_mock.rs | 64 +++----- modules/src/ics02_client/error.rs | 3 + .../src/ics02_client/handler/create_client.rs | 151 +++++++----------- .../src/ics02_client/handler/update_client.rs | 4 +- modules/src/ics02_client/msgs.rs | 70 ++++---- modules/src/ics03_connection/context_mock.rs | 11 +- modules/src/ics26_routing/context_mock.rs | 10 -- modules/src/ics26_routing/handler.rs | 18 +-- modules/src/mock_client/state.rs | 2 - modules/src/mock_context.rs | 4 +- relayer/src/tx/client.rs | 6 +- 13 files changed, 158 insertions(+), 211 deletions(-) diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index 7dbc97d5c2..6b31d7ea5b 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -133,6 +133,14 @@ impl AnyClientState { AnyClientState::Mock(mcs) => mcs.latest_height(), } } + pub fn client_type(&self) -> ClientType { + match self { + AnyClientState::Tendermint(_cs) => ClientType::Tendermint, + + #[cfg(test)] + AnyClientState::Mock(_cs) => ClientType::Mock, + } + } } impl DomainType for AnyClientState {} @@ -216,6 +224,17 @@ pub enum AnyConsensusState { Mock(MockConsensusState), } +impl AnyConsensusState { + pub fn client_type(&self) -> ClientType { + match self { + AnyConsensusState::Tendermint(_cs) => ClientType::Tendermint, + + #[cfg(test)] + AnyConsensusState::Mock(_cs) => ClientType::Mock, + } + } +} + impl DomainType for AnyConsensusState {} impl TryFrom for AnyConsensusState { diff --git a/modules/src/ics02_client/context.rs b/modules/src/ics02_client/context.rs index f58e83907d..12ff6277ec 100644 --- a/modules/src/ics02_client/context.rs +++ b/modules/src/ics02_client/context.rs @@ -22,7 +22,6 @@ pub trait ClientKeeper { fn store_client_result(&mut self, handler_res: ClientResult) -> Result<(), Error> { match handler_res { CreateResult(res) => { - self.store_client_type(res.client_id.clone(), res.client_type)?; self.store_client_state(res.client_id.clone(), res.client_state.clone())?; self.store_consensus_state( res.client_id, @@ -42,12 +41,6 @@ pub trait ClientKeeper { Ok(()) } - fn store_client_type( - &mut self, - client_id: ClientId, - client_type: ClientType, - ) -> Result<(), Error>; - fn store_client_state( &mut self, client_id: ClientId, diff --git a/modules/src/ics02_client/context_mock.rs b/modules/src/ics02_client/context_mock.rs index c1ae25ed66..bc5cf49ab8 100644 --- a/modules/src/ics02_client/context_mock.rs +++ b/modules/src/ics02_client/context_mock.rs @@ -3,6 +3,7 @@ use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; use crate::ics02_client::client_type::ClientType; use crate::ics02_client::context::{ClientKeeper, ClientReader}; use crate::ics02_client::error::{Error, Kind}; +use crate::ics02_client::state::ClientState; use crate::ics24_host::identifier::ClientId; use crate::mock_client::header::MockHeader; use crate::mock_client::state::{MockClientRecord, MockClientState, MockConsensusState}; @@ -51,38 +52,30 @@ impl MockClientContext { /// context. The client will have mock client state and a mock consensus state for the given /// height. pub fn with_client(&mut self, client_id: &ClientId, client_type: ClientType, h: Height) { - let mut client_record = MockClientRecord { - client_type, - client_state: MockClientState(MockHeader(h)), - consensus_states: HashMap::with_capacity(1), - }; - client_record - .consensus_states - .insert(h, MockConsensusState(MockHeader(h))); - self.clients.insert(client_id.clone(), client_record); - } - - /// Given a client type, an id, and a height, this function registers in the context a new - /// client record for that type and id. This client record will have no consensus states, and a - /// default client state for the input height. - pub fn with_client_type(&mut self, client_id: &ClientId, client_type: ClientType, h: Height) { - let client_record = MockClientRecord { - client_type, - client_state: MockClientState(MockHeader(h)), - consensus_states: Default::default(), - }; - self.clients.insert(client_id.clone(), client_record); + match client_type { + ClientType::Mock => { + let mut client_record = MockClientRecord { + client_state: MockClientState(MockHeader(h)), + consensus_states: HashMap::with_capacity(1), + }; + client_record + .consensus_states + .insert(h, MockConsensusState(MockHeader(h))); + self.clients.insert(client_id.clone(), client_record); + } + _ => unimplemented!(), + } } /// Given a client id and a height, registers a new client in the context and also associates /// to this client a mock client state and a mock consensus state for the input height. The type /// of this client is implicitly assumed to be Mock. pub fn with_client_consensus_state(&mut self, client_id: &ClientId, h: Height) { - let mut client_record = MockClientRecord { - client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(h)), - consensus_states: HashMap::with_capacity(1), - }; + // let mut client_record = MockClientRecord { + // client_state: MockClientState(MockHeader(h)), + // consensus_states: HashMap::with_capacity(1), + // }; + let mut client_record = self.clients.get(client_id).unwrap().clone(); client_record .consensus_states .insert(h, MockConsensusState(MockHeader(h))); @@ -93,7 +86,7 @@ impl MockClientContext { impl ClientReader for MockClientContext { fn client_type(&self, client_id: &ClientId) -> Option { match self.clients.get(client_id) { - Some(client_record) => client_record.client_type.into(), + Some(client_record) => client_record.client_state.client_type().into(), None => None, } } @@ -118,21 +111,6 @@ impl ClientReader for MockClientContext { } impl ClientKeeper for MockClientContext { - fn store_client_type( - &mut self, - client_id: ClientId, - client_type: ClientType, - ) -> Result<(), Error> { - let mut client_record = self.clients.entry(client_id).or_insert(MockClientRecord { - client_type, - consensus_states: Default::default(), - client_state: Default::default(), - }); - - client_record.client_type = client_type; - Ok(()) - } - fn store_client_state( &mut self, client_id: ClientId, @@ -141,7 +119,6 @@ impl ClientKeeper for MockClientContext { match client_state { AnyClientState::Mock(client_state) => { let mut client_record = self.clients.entry(client_id).or_insert(MockClientRecord { - client_type: ClientType::Mock, consensus_states: Default::default(), client_state, }); @@ -161,7 +138,6 @@ impl ClientKeeper for MockClientContext { match consensus_state { AnyConsensusState::Mock(consensus_state) => { let client_record = self.clients.entry(client_id).or_insert(MockClientRecord { - client_type: ClientType::Mock, consensus_states: Default::default(), client_state: Default::default(), }); diff --git a/modules/src/ics02_client/error.rs b/modules/src/ics02_client/error.rs index ad1ae177e3..a51431b1c5 100644 --- a/modules/src/ics02_client/error.rs +++ b/modules/src/ics02_client/error.rs @@ -39,6 +39,9 @@ pub enum Kind { #[error("invalid raw client consensus state")] InvalidRawConsensusState, + #[error("mismatch raw client consensus state")] + RawClientAndConsensusStateTypesMismatch { cls: ClientType, cons: ClientType }, + #[error("invalid raw header")] InvalidRawHeader, diff --git a/modules/src/ics02_client/handler/create_client.rs b/modules/src/ics02_client/handler/create_client.rs index 85eb91d14b..564d99f045 100644 --- a/modules/src/ics02_client/handler/create_client.rs +++ b/modules/src/ics02_client/handler/create_client.rs @@ -1,6 +1,5 @@ use crate::handler::{HandlerOutput, HandlerResult}; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; -use crate::ics02_client::client_type::ClientType; use crate::ics02_client::context::ClientReader; use crate::ics02_client::error::{Error, Kind}; use crate::ics02_client::handler::ClientEvent; @@ -10,7 +9,6 @@ use crate::ics24_host::identifier::ClientId; #[derive(Clone, Debug, PartialEq, Eq)] pub struct CreateClientResult { pub client_id: ClientId, - pub client_type: ClientType, pub client_state: AnyClientState, pub consensus_state: AnyConsensusState, } @@ -21,33 +19,24 @@ pub fn process( ) -> HandlerResult { let mut output = HandlerOutput::builder(); - let MsgCreateAnyClient { - client_id, - client_type, - client_state, - consensus_state, - signer: _, - } = msg; - - if ctx.client_state(&client_id).is_some() { - return Err(Kind::ClientAlreadyExists(client_id).into()); + if ctx.client_state(&msg.client_id()).is_some() { + return Err(Kind::ClientAlreadyExists(msg.client_id()).into()); } output.log("success: no client state found"); - if ctx.client_type(&client_id).is_some() { - return Err(Kind::ClientAlreadyExists(client_id).into()); + if ctx.client_type(&msg.client_id()).is_some() { + return Err(Kind::ClientAlreadyExists(msg.client_id()).into()); } output.log("success: no client type found"); - output.emit(ClientEvent::ClientCreated(client_id.clone())); + output.emit(ClientEvent::ClientCreated(msg.client_id())); Ok(output.with_result(CreateClientResult { - client_id, - client_type, - client_state, - consensus_state, + client_id: msg.client_id(), + client_state: msg.client_state(), + consensus_state: msg.consensus_state(), })) } @@ -57,6 +46,7 @@ mod tests { use std::time::Duration; use super::*; + use crate::ics02_client::client_type::ClientType; use crate::ics02_client::context_mock::MockClientContext; use crate::ics03_connection::msgs::test_util::get_dummy_account_id; use crate::ics07_tendermint::client_state::ClientState; @@ -76,26 +66,27 @@ mod tests { version_height: 42, }; - let msg = MsgCreateAnyClient { + let msg = MsgCreateAnyClient::new( client_id, - client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(height)).into(), - consensus_state: MockConsensusState(MockHeader(height)).into(), + MockClientState(MockHeader(height)).into(), + MockConsensusState(MockHeader(height)).into(), signer, - }; + ) + .unwrap(); let output = process(&ctx, msg.clone()); match output { Ok(HandlerOutput { - result, + result: _result, events, log, }) => { - assert_eq!(result.client_type, ClientType::Mock); + // FIXME AZ + //assert_eq!(result., ClientType::Mock); assert_eq!( events, - vec![ClientEvent::ClientCreated(msg.client_id).into()] + vec![ClientEvent::ClientCreated(msg.client_id()).into()] ); assert_eq!( log, @@ -111,37 +102,6 @@ mod tests { } } - #[test] - fn test_create_client_existing_client_type() { - let height = Height { - version_number: 0, - version_height: 42, - }; - let client_id: ClientId = "mockclient".parse().unwrap(); - let signer = get_dummy_account_id(); - - let mut ctx = MockClientContext::default(); - ctx.with_client_type(&client_id, ClientType::Mock, height); - - ctx.with_client_type(&client_id, ClientType::Tendermint, height); - - let msg = MsgCreateAnyClient { - client_id, - client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(height)).into(), - consensus_state: MockConsensusState(MockHeader(height)).into(), - signer, - }; - - let output = process(&ctx, msg.clone()); - - if let Err(err) = output { - assert_eq!(err.kind(), &Kind::ClientAlreadyExists(msg.client_id)); - } else { - panic!("expected an error"); - } - } - #[test] fn test_create_client_existing_client_state() { let client_id: ClientId = "mockclient".parse().unwrap(); @@ -152,28 +112,29 @@ mod tests { version_number: 0, version_height: 30, }; - ctx.with_client_consensus_state(&client_id, height); + ctx.with_client(&client_id, ClientType::Mock, height); + ctx.with_client_consensus_state(&client_id, height.increment()); - let msg = MsgCreateAnyClient { + let msg = MsgCreateAnyClient::new( client_id, - client_type: ClientType::Tendermint, - client_state: MockClientState(MockHeader(Height { + MockClientState(MockHeader(Height { version_height: 42, ..height })) .into(), - consensus_state: MockConsensusState(MockHeader(Height { + MockConsensusState(MockHeader(Height { version_height: 42, ..height })) .into(), signer, - }; + ) + .unwrap(); let output = process(&ctx, msg.clone()); if let Err(err) = output { - assert_eq!(err.kind(), &Kind::ClientAlreadyExists(msg.client_id)); + assert_eq!(err.kind(), &Kind::ClientAlreadyExists(msg.client_id())); } else { panic!("expected an error"); } @@ -188,54 +149,54 @@ mod tests { version_height: 80, }; let mut ctx = MockClientContext::default(); - ctx.with_client_consensus_state(&existing_client_id, height); + ctx.with_client(&existing_client_id, ClientType::Mock, height); let create_client_msgs: Vec = vec![ - MsgCreateAnyClient { - client_id: "newmockclient1".parse().unwrap(), - client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(Height { + MsgCreateAnyClient::new( + "newmockclient1".parse().unwrap(), + MockClientState(MockHeader(Height { version_height: 42, ..height })) .into(), - consensus_state: MockConsensusState(MockHeader(Height { + MockConsensusState(MockHeader(Height { version_height: 42, ..height })) .into(), signer, - }, - MsgCreateAnyClient { - client_id: "newmockclient2".parse().unwrap(), - client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(Height { + ) + .unwrap(), + MsgCreateAnyClient::new( + "newmockclient2".parse().unwrap(), + MockClientState(MockHeader(Height { version_height: 42, ..height })) .into(), - consensus_state: MockConsensusState(MockHeader(Height { + MockConsensusState(MockHeader(Height { version_height: 42, ..height })) .into(), signer, - }, - MsgCreateAnyClient { - client_id: "newmockclient3".parse().unwrap(), - client_type: ClientType::Tendermint, - client_state: MockClientState(MockHeader(Height { + ) + .unwrap(), + MsgCreateAnyClient::new( + "newmockclient3".parse().unwrap(), + MockClientState(MockHeader(Height { version_height: 50, ..height })) .into(), - consensus_state: MockConsensusState(MockHeader(Height { + MockConsensusState(MockHeader(Height { version_height: 50, ..height })) .into(), signer, - }, + ) + .unwrap(), ] .into_iter() .collect(); @@ -245,14 +206,15 @@ mod tests { match output { Ok(HandlerOutput { - result, + result: _, events, log, }) => { - assert_eq!(result.client_type, msg.client_type); + // FIXME AZ + // assert_eq!(result.client_type, msg.client_type); assert_eq!( events, - vec![ClientEvent::ClientCreated(msg.client_id).into()] + vec![ClientEvent::ClientCreated(msg.client_id()).into()] ); assert_eq!( log, @@ -289,26 +251,25 @@ mod tests { upgrade_path: "".to_string(), }); - let msg = MsgCreateAnyClient { + let msg = MsgCreateAnyClient::new( client_id, - client_type: ClientType::Tendermint, - client_state: tm_client_state, - consensus_state: AnyConsensusState::Tendermint(tm_header.consensus_state()), + tm_client_state, + AnyConsensusState::Tendermint(tm_header.consensus_state()), signer, - }; + ) + .unwrap(); let output = process(&ctx, msg.clone()); match output { Ok(HandlerOutput { - result, + result: _, events, log, }) => { - assert_eq!(result.client_type, ClientType::Tendermint); assert_eq!( events, - vec![ClientEvent::ClientCreated(msg.client_id).into()] + vec![ClientEvent::ClientCreated(msg.client_id()).into()] ); assert_eq!( log, diff --git a/modules/src/ics02_client/handler/update_client.rs b/modules/src/ics02_client/handler/update_client.rs index 2a146142ca..20e1e555bc 100644 --- a/modules/src/ics02_client/handler/update_client.rs +++ b/modules/src/ics02_client/handler/update_client.rs @@ -111,7 +111,7 @@ mod tests { let signer = get_dummy_account_id(); let mut ctx = MockClientContext::default(); - ctx.with_client_consensus_state(&client_id, Height::new(0, 42)); + ctx.with_client(&client_id, ClientType::Mock, Height::new(0, 42)); let msg = MsgUpdateAnyClient { client_id: "nonexistingclient".parse().unwrap(), @@ -145,7 +145,7 @@ mod tests { let mut ctx = MockClientContext::default(); for cid in &client_ids { - ctx.with_client_consensus_state(cid, initial_height); + ctx.with_client(cid, ClientType::Mock, initial_height); } for cid in &client_ids { diff --git a/modules/src/ics02_client/msgs.rs b/modules/src/ics02_client/msgs.rs index 26d7ec530e..6cb03f7f43 100644 --- a/modules/src/ics02_client/msgs.rs +++ b/modules/src/ics02_client/msgs.rs @@ -6,7 +6,6 @@ use std::convert::TryFrom; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState, AnyHeader}; -use crate::ics02_client::client_type::ClientType; use crate::ics02_client::error; use crate::ics24_host::identifier::ClientId; use crate::tx_msg::Msg; @@ -28,28 +27,41 @@ pub enum ClientMsg { /// A type of message that triggers the creation of a new on-chain (IBC) client. #[derive(Clone, Debug, PartialEq, Eq)] pub struct MsgCreateAnyClient { - pub client_id: ClientId, - pub client_type: ClientType, - pub client_state: AnyClientState, - pub consensus_state: AnyConsensusState, - pub signer: AccountId, + client_id: ClientId, + client_state: AnyClientState, + consensus_state: AnyConsensusState, + signer: AccountId, } impl MsgCreateAnyClient { pub fn new( client_id: ClientId, - client_type: ClientType, client_state: AnyClientState, consensus_state: AnyConsensusState, signer: AccountId, - ) -> Self { - MsgCreateAnyClient { + ) -> Result { + if client_state.client_type() != consensus_state.client_type() { + return Err(error::Kind::RawClientAndConsensusStateTypesMismatch { + cls: client_state.client_type(), + cons: consensus_state.client_type(), + } + .into()); + } + Ok(MsgCreateAnyClient { client_id, - client_type, client_state, consensus_state, signer, - } + }) + } + pub fn client_id(&self) -> ClientId { + self.client_id.clone() + } + pub fn client_state(&self) -> AnyClientState { + self.client_state.clone() + } + pub fn consensus_state(&self) -> AnyConsensusState { + self.consensus_state.clone() } } @@ -91,28 +103,17 @@ impl TryFrom for MsgCreateAnyClient { .client_state .ok_or_else(|| Kind::DecodeMessage.context(error::Kind::InvalidRawClientState))?; - let client_type = match raw_client_state.type_url.as_str() { - "/ibc.lightclients.tendermint.v1.ClientState" => Ok(ClientType::Tendermint), - - _ => Err( - Kind::DecodeMessage.context(error::Kind::UnknownConsensusStateType( - raw_client_state.clone().type_url, - )), - ), - }?; - let raw_consensus_state = raw .consensus_state .ok_or_else(|| Kind::DecodeMessage.context(error::Kind::InvalidRawConsensusState))?; - Ok(MsgCreateAnyClient { - client_id: raw.client_id.parse().unwrap(), - client_type, - client_state: AnyClientState::try_from(raw_client_state).unwrap(), - consensus_state: AnyConsensusState::try_from(raw_consensus_state).unwrap(), - signer: AccountId::from_str(raw.signer.as_str()) - .map_err(|e| Kind::DecodeMessage.context(e))?, - }) + Ok(MsgCreateAnyClient::new( + raw.client_id.parse().unwrap(), + AnyClientState::try_from(raw_client_state).unwrap(), + AnyConsensusState::try_from(raw_consensus_state).unwrap(), + AccountId::from_str(raw.signer.as_str()).map_err(|e| Kind::DecodeMessage.context(e))?, + ) + .map_err(|e| Kind::DecodeMessage.context(e))?) } } @@ -143,7 +144,6 @@ mod tests { use ibc_proto::ibc::core::client::v1::MsgCreateClient; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; - use crate::ics02_client::client_type::ClientType; use crate::ics02_client::msgs::MsgCreateAnyClient; use crate::ics03_connection::msgs::test_util::get_dummy_account_id; use crate::ics07_tendermint::client_state::ClientState; @@ -169,13 +169,13 @@ mod tests { upgrade_path: "".to_string(), }); - let msg = MsgCreateAnyClient { + let msg = MsgCreateAnyClient::new( client_id, - client_type: ClientType::Tendermint, - client_state: tm_client_state, - consensus_state: AnyConsensusState::Tendermint(tm_header.consensus_state()), + tm_client_state, + AnyConsensusState::Tendermint(tm_header.consensus_state()), signer, - }; + ) + .unwrap(); let raw = MsgCreateClient::from(msg.clone()); let msg_back = MsgCreateAnyClient::try_from(raw.clone()).unwrap(); diff --git a/modules/src/ics03_connection/context_mock.rs b/modules/src/ics03_connection/context_mock.rs index 760debbf14..03f96cc3f0 100644 --- a/modules/src/ics03_connection/context_mock.rs +++ b/modules/src/ics03_connection/context_mock.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use crate::context::{ChainReader, SelfHeader}; use crate::context_mock::MockChainContext; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; +use crate::ics02_client::client_type::ClientType; use crate::ics02_client::context::ClientReader; use crate::ics02_client::context_mock::MockClientContext; use crate::ics03_connection::connection::ConnectionEnd; @@ -39,10 +40,16 @@ impl MockConnectionContext { &self.client_context } - pub fn with_client_state(self, client_id: &ClientId, latest_client_height: u64) -> Self { + pub fn with_client( + self, + client_id: &ClientId, + client_type: ClientType, + latest_client_height: u64, + ) -> Self { let mut client_context = self.client_context().clone(); - client_context.with_client_consensus_state( + client_context.with_client( client_id, + client_type, Height { version_number: 0, version_height: latest_client_height, diff --git a/modules/src/ics26_routing/context_mock.rs b/modules/src/ics26_routing/context_mock.rs index 608fae9866..e5b6352e1c 100644 --- a/modules/src/ics26_routing/context_mock.rs +++ b/modules/src/ics26_routing/context_mock.rs @@ -114,16 +114,6 @@ impl ConnectionKeeper for MockICS26Context { } impl ClientKeeper for MockICS26Context { - fn store_client_type( - &mut self, - client_id: ClientId, - client_type: ClientType, - ) -> Result<(), ICS2Error> { - self.client_context - .store_client_type(client_id, client_type)?; - Ok(()) - } - fn store_client_state( &mut self, client_id: ClientId, diff --git a/modules/src/ics26_routing/handler.rs b/modules/src/ics26_routing/handler.rs index 83ee2c59ec..a38a0d39b9 100644 --- a/modules/src/ics26_routing/handler.rs +++ b/modules/src/ics26_routing/handler.rs @@ -62,7 +62,6 @@ mod tests { use std::str::FromStr; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; - use crate::ics02_client::client_type::ClientType; use crate::ics02_client::msgs::{ClientMsg, MsgCreateAnyClient}; use crate::ics03_connection::msgs::test_util::get_dummy_account_id; use crate::ics24_host::identifier::ClientId; @@ -85,15 +84,14 @@ mod tests { want_pass: bool, } - let msg = MsgCreateAnyClient { - client_id: ClientId::from_str("client_id").unwrap(), - client_type: ClientType::Mock, - client_state: AnyClientState::from(MockClientState(MockHeader(Height::new(0, 42)))), - consensus_state: AnyConsensusState::from(MockConsensusState(MockHeader(Height::new( - 0, 42, - )))), - signer: get_dummy_account_id(), - }; + let msg = MsgCreateAnyClient::new( + ClientId::from_str("client_id").unwrap(), + AnyClientState::from(MockClientState(MockHeader(Height::new(0, 42)))), + AnyConsensusState::from(MockConsensusState(MockHeader(Height::new(0, 42)))), + get_dummy_account_id(), + ) + .unwrap(); + let envelope = ICS26Envelope::ICS2Msg(ClientMsg::CreateClient(msg)); let params = DispatchParams { diff --git a/modules/src/mock_client/state.rs b/modules/src/mock_client/state.rs index 6729938dac..f8d59309a3 100644 --- a/modules/src/mock_client/state.rs +++ b/modules/src/mock_client/state.rs @@ -22,8 +22,6 @@ use crate::Height; /// For testing ICS02 handlers mostly, cf. `MockClientContext`. #[derive(Clone, Debug)] pub struct MockClientRecord { - /// The type of this client. - pub client_type: ClientType, /// Mapping of heights to consensus states for this client. pub consensus_states: HashMap, /// The client state (representing only the latest height at the moment). diff --git a/modules/src/mock_context.rs b/modules/src/mock_context.rs index 6a082e65da..014ea4cff7 100644 --- a/modules/src/mock_context.rs +++ b/modules/src/mock_context.rs @@ -11,6 +11,7 @@ use crate::mock_client::header::MockHeader; use crate::mock_client::state::{MockClientRecord, MockClientState, MockConsensusState}; use crate::Height; +use crate::ics02_client::state::ClientState; use std::cmp::min; use std::collections::HashMap; @@ -62,7 +63,6 @@ impl MockContext { let mut clients = self.clients.clone(); let mut client_record = MockClientRecord { - client_type: ClientType::Mock, client_state: MockClientState(MockHeader(height)), consensus_states: HashMap::with_capacity(1), }; @@ -176,7 +176,7 @@ impl ConnectionKeeper for MockContext { impl ClientReader for MockContext { fn client_type(&self, client_id: &ClientId) -> Option { match self.clients.get(client_id) { - Some(client_record) => client_record.client_type.into(), + Some(client_record) => client_record.client_state.client_type().into(), None => None, } } diff --git a/relayer/src/tx/client.rs b/relayer/src/tx/client.rs index 6224faa602..85ca85b22e 100644 --- a/relayer/src/tx/client.rs +++ b/relayer/src/tx/client.rs @@ -87,11 +87,13 @@ pub fn create_client(opts: CreateClientOptions) -> Result<(), Error> { // Build the domain type message let new_msg = MsgCreateAnyClient::new( opts.dest_client_id, - ClientType::Tendermint, any_client_state, any_consensus_state, signer, - ); + ) + .map_err(|e| { + Kind::MessageTransaction("failed to build the create client message".into()).context(e) + })?; // Create a proto any message let mut proto_msgs: Vec = Vec::new(); From 03fa55479ed5cab2de4ca61547c66f84c73b06f0 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Wed, 14 Oct 2020 19:25:34 +0200 Subject: [PATCH 3/5] cleanup --- modules/src/ics02_client/client_def.rs | 26 ++++++------------- modules/src/ics02_client/context.rs | 4 +-- modules/src/ics02_client/context_mock.rs | 4 --- modules/src/ics02_client/error.rs | 5 +++- .../src/ics02_client/handler/create_client.rs | 4 --- .../src/ics02_client/handler/update_client.rs | 1 - modules/src/ics02_client/msgs.rs | 4 +-- modules/src/ics18_relayer/utils.rs | 2 -- modules/src/mock_client/state.rs | 4 +-- 9 files changed, 18 insertions(+), 36 deletions(-) diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index 6b31d7ea5b..c20cc6de71 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -125,20 +125,20 @@ pub enum AnyClientState { } impl AnyClientState { - pub fn height(&self) -> Height { + pub fn latest_height(&self) -> Height { match self { - AnyClientState::Tendermint(tcs) => tcs.latest_height(), + Self::Tendermint(tm_state) => tm_state.latest_height(), #[cfg(test)] - AnyClientState::Mock(mcs) => mcs.latest_height(), + Self::Mock(mock_state) => mock_state.latest_height(), } } pub fn client_type(&self) -> ClientType { match self { - AnyClientState::Tendermint(_cs) => ClientType::Tendermint, + Self::Tendermint(state) => state.client_type(), #[cfg(test)] - AnyClientState::Mock(_cs) => ClientType::Mock, + Self::Mock(state) => state.client_type(), } } } @@ -189,21 +189,11 @@ impl ClientState for AnyClientState { } fn client_type(&self) -> ClientType { - match self { - Self::Tendermint(state) => state.client_type(), - - #[cfg(test)] - Self::Mock(state) => state.client_type(), - } + self.client_type() } fn latest_height(&self) -> Height { - match self { - Self::Tendermint(tm_state) => tm_state.latest_height(), - - #[cfg(test)] - Self::Mock(mock_state) => mock_state.latest_height(), - } + self.latest_height() } fn is_frozen(&self) -> bool { @@ -276,7 +266,7 @@ impl From for Any { impl ConsensusState for AnyConsensusState { fn client_type(&self) -> ClientType { - todo!() + self.client_type() } fn root(&self) -> &CommitmentRoot { diff --git a/modules/src/ics02_client/context.rs b/modules/src/ics02_client/context.rs index 12ff6277ec..251f68ea03 100644 --- a/modules/src/ics02_client/context.rs +++ b/modules/src/ics02_client/context.rs @@ -25,7 +25,7 @@ pub trait ClientKeeper { self.store_client_state(res.client_id.clone(), res.client_state.clone())?; self.store_consensus_state( res.client_id, - res.client_state.height(), + res.client_state.latest_height(), res.consensus_state, )?; } @@ -33,7 +33,7 @@ pub trait ClientKeeper { self.store_client_state(res.client_id.clone(), res.client_state.clone())?; self.store_consensus_state( res.client_id, - res.client_state.height(), + res.client_state.latest_height(), res.consensus_state, )?; } diff --git a/modules/src/ics02_client/context_mock.rs b/modules/src/ics02_client/context_mock.rs index bc5cf49ab8..2600fd735f 100644 --- a/modules/src/ics02_client/context_mock.rs +++ b/modules/src/ics02_client/context_mock.rs @@ -71,10 +71,6 @@ impl MockClientContext { /// to this client a mock client state and a mock consensus state for the input height. The type /// of this client is implicitly assumed to be Mock. pub fn with_client_consensus_state(&mut self, client_id: &ClientId, h: Height) { - // let mut client_record = MockClientRecord { - // client_state: MockClientState(MockHeader(h)), - // consensus_states: HashMap::with_capacity(1), - // }; let mut client_record = self.clients.get(client_id).unwrap().clone(); client_record .consensus_states diff --git a/modules/src/ics02_client/error.rs b/modules/src/ics02_client/error.rs index a51431b1c5..422ea9fa89 100644 --- a/modules/src/ics02_client/error.rs +++ b/modules/src/ics02_client/error.rs @@ -40,7 +40,10 @@ pub enum Kind { InvalidRawConsensusState, #[error("mismatch raw client consensus state")] - RawClientAndConsensusStateTypesMismatch { cls: ClientType, cons: ClientType }, + RawClientAndConsensusStateTypesMismatch { + state_type: ClientType, + consensus_type: ClientType, + }, #[error("invalid raw header")] InvalidRawHeader, diff --git a/modules/src/ics02_client/handler/create_client.rs b/modules/src/ics02_client/handler/create_client.rs index 564d99f045..b1e0e83fee 100644 --- a/modules/src/ics02_client/handler/create_client.rs +++ b/modules/src/ics02_client/handler/create_client.rs @@ -82,8 +82,6 @@ mod tests { events, log, }) => { - // FIXME AZ - //assert_eq!(result., ClientType::Mock); assert_eq!( events, vec![ClientEvent::ClientCreated(msg.client_id()).into()] @@ -210,8 +208,6 @@ mod tests { events, log, }) => { - // FIXME AZ - // assert_eq!(result.client_type, msg.client_type); assert_eq!( events, vec![ClientEvent::ClientCreated(msg.client_id()).into()] diff --git a/modules/src/ics02_client/handler/update_client.rs b/modules/src/ics02_client/handler/update_client.rs index 20e1e555bc..0f1a733b76 100644 --- a/modules/src/ics02_client/handler/update_client.rs +++ b/modules/src/ics02_client/handler/update_client.rs @@ -5,7 +5,6 @@ use crate::ics02_client::error::{Error, Kind}; use crate::ics02_client::handler::{ClientEvent, ClientResult}; use crate::ics02_client::msgs::MsgUpdateAnyClient; -use crate::ics02_client::state::ClientState; use crate::ics24_host::identifier::ClientId; #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/modules/src/ics02_client/msgs.rs b/modules/src/ics02_client/msgs.rs index 6cb03f7f43..63da0f8f37 100644 --- a/modules/src/ics02_client/msgs.rs +++ b/modules/src/ics02_client/msgs.rs @@ -42,8 +42,8 @@ impl MsgCreateAnyClient { ) -> Result { if client_state.client_type() != consensus_state.client_type() { return Err(error::Kind::RawClientAndConsensusStateTypesMismatch { - cls: client_state.client_type(), - cons: consensus_state.client_type(), + state_type: client_state.client_type(), + consensus_type: consensus_state.client_type(), } .into()); } diff --git a/modules/src/ics18_relayer/utils.rs b/modules/src/ics18_relayer/utils.rs index 608c5e6f6d..3d23cff284 100644 --- a/modules/src/ics18_relayer/utils.rs +++ b/modules/src/ics18_relayer/utils.rs @@ -1,7 +1,6 @@ use crate::ics02_client::client_def::AnyHeader; use crate::ics02_client::header::Header; use crate::ics02_client::msgs::{ClientMsg, MsgUpdateAnyClient}; -use crate::ics02_client::state::ClientState; use crate::ics03_connection::msgs::test_util::get_dummy_account_id; use crate::ics18_relayer::context::ICS18Context; use crate::ics18_relayer::error::{Error, Kind}; @@ -53,7 +52,6 @@ where #[cfg(test)] mod tests { - use crate::ics02_client::state::ClientState; use crate::ics18_relayer::context::ICS18Context; use crate::ics18_relayer::context_mock::MockICS18Context; use crate::ics18_relayer::utils::create_client_update_datagram; diff --git a/modules/src/mock_client/state.rs b/modules/src/mock_client/state.rs index f8d59309a3..494d084863 100644 --- a/modules/src/mock_client/state.rs +++ b/modules/src/mock_client/state.rs @@ -22,10 +22,10 @@ use crate::Height; /// For testing ICS02 handlers mostly, cf. `MockClientContext`. #[derive(Clone, Debug)] pub struct MockClientRecord { - /// Mapping of heights to consensus states for this client. - pub consensus_states: HashMap, /// The client state (representing only the latest height at the moment). pub client_state: MockClientState, + /// Mapping of heights to consensus states for this client. + pub consensus_states: HashMap, } /// A mock of a client state. For an example of a real structure that this mocks, you can see From 4df37816c8a98dd8afece873b2e09c0dcbb4d22f Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 15 Oct 2020 10:27:51 +0200 Subject: [PATCH 4/5] Remove some unwraps --- modules/src/ics02_client/msgs.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/src/ics02_client/msgs.rs b/modules/src/ics02_client/msgs.rs index 63da0f8f37..fae9bc6af9 100644 --- a/modules/src/ics02_client/msgs.rs +++ b/modules/src/ics02_client/msgs.rs @@ -108,9 +108,12 @@ impl TryFrom for MsgCreateAnyClient { .ok_or_else(|| Kind::DecodeMessage.context(error::Kind::InvalidRawConsensusState))?; Ok(MsgCreateAnyClient::new( - raw.client_id.parse().unwrap(), - AnyClientState::try_from(raw_client_state).unwrap(), - AnyConsensusState::try_from(raw_consensus_state).unwrap(), + ClientId::from_str(raw.client_id.as_str()) + .map_err(|e| Kind::DecodeMessage.context(e))?, + AnyClientState::try_from(raw_client_state) + .map_err(|e| Kind::DecodeMessage.context(e))?, + AnyConsensusState::try_from(raw_consensus_state) + .map_err(|e| Kind::DecodeMessage.context(e))?, AccountId::from_str(raw.signer.as_str()).map_err(|e| Kind::DecodeMessage.context(e))?, ) .map_err(|e| Kind::DecodeMessage.context(e))?) From 9f661824d02290ea67fdf0fbcfa5c9752e681989 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 15 Oct 2020 12:03:19 +0200 Subject: [PATCH 5/5] Adi's review comments --- modules/src/ics02_client/context.rs | 6 ++++ modules/src/ics02_client/context_mock.rs | 18 ++++++++++ modules/src/ics02_client/error.rs | 2 +- .../src/ics02_client/handler/create_client.rs | 33 ++++--------------- modules/src/ics26_routing/context_mock.rs | 10 ++++++ modules/src/mock_client/state.rs | 2 ++ modules/src/mock_context.rs | 1 + 7 files changed, 44 insertions(+), 28 deletions(-) diff --git a/modules/src/ics02_client/context.rs b/modules/src/ics02_client/context.rs index 251f68ea03..f4c5c2c878 100644 --- a/modules/src/ics02_client/context.rs +++ b/modules/src/ics02_client/context.rs @@ -19,6 +19,12 @@ pub trait ClientReader { /// Defines the write-only part of ICS2 (client functions) context. pub trait ClientKeeper { + fn store_client_type( + &mut self, + client_id: ClientId, + client_type: ClientType, + ) -> Result<(), Error>; + fn store_client_result(&mut self, handler_res: ClientResult) -> Result<(), Error> { match handler_res { CreateResult(res) => { diff --git a/modules/src/ics02_client/context_mock.rs b/modules/src/ics02_client/context_mock.rs index 2600fd735f..e7bbee59dd 100644 --- a/modules/src/ics02_client/context_mock.rs +++ b/modules/src/ics02_client/context_mock.rs @@ -55,6 +55,7 @@ impl MockClientContext { match client_type { ClientType::Mock => { let mut client_record = MockClientRecord { + client_type: ClientType::Mock, client_state: MockClientState(MockHeader(h)), consensus_states: HashMap::with_capacity(1), }; @@ -107,6 +108,21 @@ impl ClientReader for MockClientContext { } impl ClientKeeper for MockClientContext { + fn store_client_type( + &mut self, + client_id: ClientId, + client_type: ClientType, + ) -> Result<(), Error> { + let mut client_record = self.clients.entry(client_id).or_insert(MockClientRecord { + client_type, + consensus_states: Default::default(), + client_state: Default::default(), + }); + + client_record.client_type = client_type; + Ok(()) + } + fn store_client_state( &mut self, client_id: ClientId, @@ -115,6 +131,7 @@ impl ClientKeeper for MockClientContext { match client_state { AnyClientState::Mock(client_state) => { let mut client_record = self.clients.entry(client_id).or_insert(MockClientRecord { + client_type: ClientType::Mock, consensus_states: Default::default(), client_state, }); @@ -135,6 +152,7 @@ impl ClientKeeper for MockClientContext { AnyConsensusState::Mock(consensus_state) => { let client_record = self.clients.entry(client_id).or_insert(MockClientRecord { consensus_states: Default::default(), + client_type: ClientType::Mock, client_state: Default::default(), }); client_record diff --git a/modules/src/ics02_client/error.rs b/modules/src/ics02_client/error.rs index 422ea9fa89..ed6cc21737 100644 --- a/modules/src/ics02_client/error.rs +++ b/modules/src/ics02_client/error.rs @@ -39,7 +39,7 @@ pub enum Kind { #[error("invalid raw client consensus state")] InvalidRawConsensusState, - #[error("mismatch raw client consensus state")] + #[error("mismatch raw client consensus state")] RawClientAndConsensusStateTypesMismatch { state_type: ClientType, consensus_type: ClientType, diff --git a/modules/src/ics02_client/handler/create_client.rs b/modules/src/ics02_client/handler/create_client.rs index b1e0e83fee..0dd2574caf 100644 --- a/modules/src/ics02_client/handler/create_client.rs +++ b/modules/src/ics02_client/handler/create_client.rs @@ -1,5 +1,6 @@ use crate::handler::{HandlerOutput, HandlerResult}; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; +use crate::ics02_client::client_type::ClientType; use crate::ics02_client::context::ClientReader; use crate::ics02_client::error::{Error, Kind}; use crate::ics02_client::handler::ClientEvent; @@ -9,6 +10,7 @@ use crate::ics24_host::identifier::ClientId; #[derive(Clone, Debug, PartialEq, Eq)] pub struct CreateClientResult { pub client_id: ClientId, + pub client_type: ClientType, pub client_state: AnyClientState, pub consensus_state: AnyConsensusState, } @@ -25,16 +27,11 @@ pub fn process( output.log("success: no client state found"); - if ctx.client_type(&msg.client_id()).is_some() { - return Err(Kind::ClientAlreadyExists(msg.client_id()).into()); - } - - output.log("success: no client type found"); - output.emit(ClientEvent::ClientCreated(msg.client_id())); Ok(output.with_result(CreateClientResult { client_id: msg.client_id(), + client_type: msg.client_state().client_type(), client_state: msg.client_state(), consensus_state: msg.consensus_state(), })) @@ -86,13 +83,7 @@ mod tests { events, vec![ClientEvent::ClientCreated(msg.client_id()).into()] ); - assert_eq!( - log, - vec![ - "success: no client state found".to_string(), - "success: no client type found".to_string() - ] - ); + assert_eq!(log, vec!["success: no client state found".to_string()]); } Err(err) => { panic!("unexpected error: {}", err); @@ -212,13 +203,7 @@ mod tests { events, vec![ClientEvent::ClientCreated(msg.client_id()).into()] ); - assert_eq!( - log, - vec![ - "success: no client state found".to_string(), - "success: no client type found".to_string() - ] - ); + assert_eq!(log, vec!["success: no client state found".to_string()]); } Err(err) => { panic!("unexpected error: {}", err); @@ -267,13 +252,7 @@ mod tests { events, vec![ClientEvent::ClientCreated(msg.client_id()).into()] ); - assert_eq!( - log, - vec![ - "success: no client state found".to_string(), - "success: no client type found".to_string() - ] - ); + assert_eq!(log, vec!["success: no client state found".to_string()]); } Err(err) => { panic!("unexpected error: {}", err); diff --git a/modules/src/ics26_routing/context_mock.rs b/modules/src/ics26_routing/context_mock.rs index e5b6352e1c..608fae9866 100644 --- a/modules/src/ics26_routing/context_mock.rs +++ b/modules/src/ics26_routing/context_mock.rs @@ -114,6 +114,16 @@ impl ConnectionKeeper for MockICS26Context { } impl ClientKeeper for MockICS26Context { + fn store_client_type( + &mut self, + client_id: ClientId, + client_type: ClientType, + ) -> Result<(), ICS2Error> { + self.client_context + .store_client_type(client_id, client_type)?; + Ok(()) + } + fn store_client_state( &mut self, client_id: ClientId, diff --git a/modules/src/mock_client/state.rs b/modules/src/mock_client/state.rs index 494d084863..f50328dee7 100644 --- a/modules/src/mock_client/state.rs +++ b/modules/src/mock_client/state.rs @@ -22,6 +22,8 @@ use crate::Height; /// For testing ICS02 handlers mostly, cf. `MockClientContext`. #[derive(Clone, Debug)] pub struct MockClientRecord { + /// The type of this client. + pub client_type: ClientType, /// The client state (representing only the latest height at the moment). pub client_state: MockClientState, /// Mapping of heights to consensus states for this client. diff --git a/modules/src/mock_context.rs b/modules/src/mock_context.rs index 014ea4cff7..019c233ea5 100644 --- a/modules/src/mock_context.rs +++ b/modules/src/mock_context.rs @@ -63,6 +63,7 @@ impl MockContext { let mut clients = self.clients.clone(); let mut client_record = MockClientRecord { + client_type: ClientType::Mock, client_state: MockClientState(MockHeader(height)), consensus_states: HashMap::with_capacity(1), };