Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic support for ICS09 localhost clients #3611

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion crates/relayer-cli/src/cli_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use ibc_relayer::{
config::Config,
spawn,
};
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId};

use crate::error::Error;
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/create/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use ibc_relayer::chain::requests::{
use ibc_relayer::channel::Channel;
use ibc_relayer::connection::Connection;
use ibc_relayer::foreign_client::ForeignClient;
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics03_connection::connection::IdentifiedConnectionEnd;
use ibc_relayer_types::core::ics04_channel::channel::Ordering;
use ibc_relayer_types::core::ics04_channel::version::Version;
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/create/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use ibc_relayer::chain::handle::ChainHandle;
use ibc_relayer::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight};
use ibc_relayer::connection::Connection;
use ibc_relayer::foreign_client::ForeignClient;
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId};

use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair};
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/query/channel_ends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use ibc_relayer::chain::requests::{
};
use ibc_relayer::client_state::AnyClientState;
use ibc_relayer::registry::Registry;
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics03_connection::connection::ConnectionEnd;
use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, State};
use ibc_relayer_types::core::ics24_host::identifier::ChainId;
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/query/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use ibc_relayer::chain::requests::{
QueryConnectionRequest, QueryHeight,
};
use ibc_relayer::registry::Registry;
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, State};
use ibc_relayer_types::core::ics24_host::identifier::{
ChainId, ChannelId, ConnectionId, PortChannelId, PortId,
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/query/clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use ibc_relayer::chain::handle::ChainHandle;
use serde::Serialize;

use ibc_relayer::chain::requests::{PageRequest, QueryClientStatesRequest};
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId};

use crate::cli_utils::spawn_chain_runtime;
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/query/connections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use ibc_relayer::chain::handle::ChainHandle;
use ibc_relayer::chain::requests::{
IncludeProof, PageRequest, QueryClientStateRequest, QueryConnectionsRequest, QueryHeight,
};
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ConnectionId};

use crate::cli_utils::spawn_chain_runtime;
Expand Down
1 change: 0 additions & 1 deletion crates/relayer-cli/src/commands/tx/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use ibc_relayer::config::Config;
use ibc_relayer::event::IbcEventWithHeight;
use ibc_relayer::foreign_client::{CreateOptions, ForeignClient};
use ibc_relayer::{chain::handle::ChainHandle, config::GenesisRestart};
use ibc_relayer_types::core::ics02_client::client_state::ClientState;
use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId};
use ibc_relayer_types::events::IbcEvent;
use ibc_relayer_types::Height;
Expand Down
47 changes: 22 additions & 25 deletions crates/relayer-types/src/clients/ics07_tendermint/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use tendermint_light_client_verifier::options::Options;
use crate::clients::ics07_tendermint::error::Error;
use crate::clients::ics07_tendermint::header::Header as TmHeader;
use crate::core::ics02_client::client_state::{
ClientState as Ics2ClientState, UpgradeOptions as CoreUpgradeOptions,
ClientState as Ics2ClientState, UpgradableClientState,
};
use crate::core::ics02_client::client_type::ClientType;
use crate::core::ics02_client::error::Error as Ics02Error;
Expand Down Expand Up @@ -199,36 +199,15 @@ pub struct UpgradeOptions {
pub unbonding_period: Duration,
}

impl CoreUpgradeOptions for UpgradeOptions {}

impl Ics2ClientState for ClientState {
fn chain_id(&self) -> ChainId {
self.chain_id.clone()
}

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

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

fn frozen_height(&self) -> Option<Height> {
self.frozen_height
}
impl UpgradableClientState for ClientState {
type UpgradeOptions = UpgradeOptions;

fn upgrade(
&mut self,
upgrade_height: Height,
upgrade_options: &dyn CoreUpgradeOptions,
upgrade_options: UpgradeOptions,
chain_id: ChainId,
) {
let upgrade_options = upgrade_options
.as_any()
.downcast_ref::<UpgradeOptions>()
.expect("UpgradeOptions not of type Tendermint");

// Reset custom fields to zero values
self.trusting_period = ZERO_DURATION;
self.trust_threshold = TrustThreshold::CLIENT_STATE_RESET;
Expand All @@ -242,6 +221,24 @@ impl Ics2ClientState for ClientState {
self.unbonding_period = upgrade_options.unbonding_period;
self.chain_id = chain_id;
}
}

impl Ics2ClientState for ClientState {
fn chain_id(&self) -> ChainId {
self.chain_id.clone()
}

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

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

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

fn expired(&self, elapsed: Duration) -> bool {
elapsed > self.trusting_period
Expand Down
11 changes: 11 additions & 0 deletions crates/relayer-types/src/clients/ics09_localhost/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! ICS 09: Loopback Client
//! Loopback client, designed to be used for interaction over the
//! IBC interface with modules present on the same ledger.
//!
//! Loopback clients may be useful in cases where the calling module
//! does not have prior knowledge of where precisely the destination
//! module lives and would like to use the uniform IBC message-passing
//! interface (similar to 127.0.0.1 in TCP/IP).

pub mod v1;
pub mod v2;
119 changes: 119 additions & 0 deletions crates/relayer-types/src/clients/ics09_localhost/v1/client_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
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::lightclients::localhost::v1::ClientState as RawClientState;
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;

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

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

impl ClientState {
pub fn new(chain_id: ChainId, height: Height) -> ClientState {
Self { chain_id, height }
}

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

impl Ics02ClientState for ClientState {
fn chain_id(&self) -> ChainId {
self.chain_id.clone()
}

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

fn latest_height(&self) -> Height {
self.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 {
chain_id: ChainId::from_string(raw.chain_id.as_str()),
height: raw
.height
.ok_or_else(Error::missing_height)?
.try_into()
.map_err(|_| Error::missing_height())?,
})
}
}

impl From<ClientState> for RawClientState {
fn from(value: ClientState) -> Self {
Self {
chain_id: value.chain_id.to_string(),
height: Some(value.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_V1_CLIENT_STATE_TYPE_URL => {
decode_client_state(raw.value.deref()).map_err(Into::into)
}
_ => Err(Ics02Error::unexpected_client_state_type(
LOCALHOST_V1_CLIENT_STATE_TYPE_URL.to_string(),
raw.type_url,
)),
}
}
}

impl From<ClientState> for Any {
fn from(client_state: ClientState) -> Self {
Any {
type_url: LOCALHOST_V1_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/v1/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" },

MissingHeight
|_| { "missing 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())
}
}
2 changes: 2 additions & 0 deletions crates/relayer-types/src/clients/ics09_localhost/v1/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod client_state;
pub mod error;
Loading