Skip to content

Commit

Permalink
Add support for localhost.v2 client state
Browse files Browse the repository at this point in the history
  • Loading branch information
romac committed Sep 13, 2023
1 parent 2b7b2b0 commit 97a12be
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::Height;

use super::error::Error;

pub const LOCALHOST_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.localhost.v1.ClientState";
pub const LOCALHOST_V1_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.localhost.v1.ClientState";

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ClientState {
Expand Down Expand Up @@ -98,11 +98,11 @@ impl TryFrom<Any> for ClientState {
}

match raw.type_url.as_str() {
LOCALHOST_CLIENT_STATE_TYPE_URL => {
LOCALHOST_V1_CLIENT_STATE_TYPE_URL => {
decode_client_state(raw.value.deref()).map_err(Into::into)
}
_ => Err(Ics02Error::unexpected_client_state_type(
LOCALHOST_CLIENT_STATE_TYPE_URL.to_string(),
LOCALHOST_V1_CLIENT_STATE_TYPE_URL.to_string(),
raw.type_url,
)),
}
Expand All @@ -112,7 +112,7 @@ impl TryFrom<Any> for ClientState {
impl From<ClientState> for Any {
fn from(client_state: ClientState) -> Self {
Any {
type_url: LOCALHOST_CLIENT_STATE_TYPE_URL.to_string(),
type_url: LOCALHOST_V1_CLIENT_STATE_TYPE_URL.to_string(),
value: Protobuf::<RawClientState>::encode_vec(&client_state),
}
}
Expand Down
12 changes: 0 additions & 12 deletions crates/relayer-types/src/clients/ics09_localhost/v1/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use flex_error::{define_error, TraceError};
use crate::core::ics02_client::error::Error as Ics02Error;
use crate::core::ics24_host::error::ValidationError;

use crate::Height;

define_error! {
#[derive(Debug, PartialEq, Eq)]
Error {
Expand All @@ -31,16 +29,6 @@ define_error! {
Decode
[ TraceError<prost::DecodeError> ]
|_| { "decode error" },

InsufficientHeight
{
latest_height: Height,
target_height: Height,
}
|e| {
format_args!("the height is insufficient: latest_height={0} target_height={1}",
e.latest_height, e.target_height)
},
}
}

Expand Down
126 changes: 126 additions & 0 deletions crates/relayer-types/src/clients/ics09_localhost/v2/client_state.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,128 @@
use std::convert::{TryFrom, TryInto};
use std::time::Duration;

use prost::Message;
use serde::{Deserialize, Serialize};

use ibc_proto::google::protobuf::Any;
use ibc_proto::ibc::core::client::v1::Height as RawHeight;
use ibc_proto::protobuf::Protobuf;

use crate::core::ics02_client::client_state::ClientState as Ics02ClientState;
use crate::core::ics02_client::client_type::ClientType;
use crate::core::ics02_client::error::Error as Ics02Error;
use crate::core::ics24_host::identifier::ChainId;
use crate::Height;

use super::error::Error;

// use ibc_proto::ibc::lightclients::localhost::v2::ClientState as RawClientState;

/// ClientState defines the 09-localhost client state
#[derive(Serialize, Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RawClientState {
/// the latest block height
#[prost(message, optional, tag = "1")]
pub latest_height: ::core::option::Option<RawHeight>,
}

pub const LOCALHOST_V2_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.localhost.v2.ClientState";

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ClientState {
pub latest_height: Height,
}

impl ClientState {
pub fn new(latest_height: Height) -> ClientState {
Self { latest_height }
}

pub fn height(&self) -> Height {
self.latest_height
}
}

impl Ics02ClientState for ClientState {
fn chain_id(&self) -> ChainId {
unimplemented!()
}

fn client_type(&self) -> ClientType {
ClientType::Localhost
}

fn latest_height(&self) -> Height {
self.latest_height
}

fn frozen_height(&self) -> Option<Height> {
None
}

fn expired(&self, _elapsed: Duration) -> bool {
false
}
}

impl Protobuf<RawClientState> for ClientState {}

impl TryFrom<RawClientState> for ClientState {
type Error = Error;

fn try_from(raw: RawClientState) -> Result<Self, Self::Error> {
Ok(Self {
latest_height: raw
.latest_height
.ok_or_else(Error::missing_latest_height)?
.try_into()
.map_err(|_| Error::missing_latest_height())?,
})
}
}

impl From<ClientState> for RawClientState {
fn from(value: ClientState) -> Self {
Self {
latest_height: Some(value.latest_height.into()),
}
}
}

impl Protobuf<Any> for ClientState {}

impl TryFrom<Any> for ClientState {
type Error = Ics02Error;

fn try_from(raw: Any) -> Result<Self, Self::Error> {
use bytes::Buf;
use core::ops::Deref;

fn decode_client_state<B: Buf>(buf: B) -> Result<ClientState, Error> {
RawClientState::decode(buf)
.map_err(Error::decode)?
.try_into()
}

match raw.type_url.as_str() {
LOCALHOST_V2_CLIENT_STATE_TYPE_URL => {
decode_client_state(raw.value.deref()).map_err(Into::into)
}
_ => Err(Ics02Error::unexpected_client_state_type(
LOCALHOST_V2_CLIENT_STATE_TYPE_URL.to_string(),
raw.type_url,
)),
}
}
}

impl From<ClientState> for Any {
fn from(client_state: ClientState) -> Self {
Any {
type_url: LOCALHOST_V2_CLIENT_STATE_TYPE_URL.to_string(),
value: Protobuf::<RawClientState>::encode_vec(&client_state),
}
}
}
39 changes: 39 additions & 0 deletions crates/relayer-types/src/clients/ics09_localhost/v2/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use flex_error::{define_error, TraceError};

use crate::core::ics02_client::error::Error as Ics02Error;
use crate::core::ics24_host::error::ValidationError;

define_error! {
#[derive(Debug, PartialEq, Eq)]
Error {
InvalidRawClientState
{ reason: String }
|e| { format_args!("invalid raw client state: {}", e.reason) },

InvalidChainIdentifier
[ ValidationError ]
|_| { "invalid chain identifier" },

MissingLatestHeight
|_| { "missing latest height" },

InvalidChainId
{ raw_value: String }
[ ValidationError ]
|e| { format_args!("invalid chain identifier: {}", e.raw_value) },

InvalidRawHeight
{ raw_height: u64 }
|e| { format_args!("invalid raw height: {}", e.raw_height) },

Decode
[ TraceError<prost::DecodeError> ]
|_| { "decode error" },
}
}

impl From<Error> for Ics02Error {
fn from(e: Error) -> Self {
Self::client_specific(e.to_string())
}
}
1 change: 1 addition & 0 deletions crates/relayer-types/src/clients/ics09_localhost/v2/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod client_state;
pub mod error;
Loading

0 comments on commit 97a12be

Please sign in to comment.