Skip to content

Commit

Permalink
imp(ibc-client): rm TryFrom<Error = ClientError> restriction (#1204)
Browse files Browse the repository at this point in the history
* rm concrete Error type

* update ibc-core

* update tm client

* update cw-context

* Convertible in reverse direction

* update code

* use Convertible<Any>

* rm redundant bound

---------

Co-authored-by: Sean Chen <[email protected]>
  • Loading branch information
rnbguy and seanchen1991 authored Apr 30, 2024
1 parent ed4f8cd commit dc116da
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 67 deletions.
8 changes: 6 additions & 2 deletions ibc-clients/cw-context/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ use crate::context::Context;
/// Enables users to integrate their implemented light client by introducing
/// their client state and consensus state types into the generic [`Context`]
/// object.
pub trait ClientType<'a>: Sized {
pub trait ClientType<'a>: Sized
where
<Self::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<Self::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
type ClientState: ClientStateExecution<Context<'a, Self>> + Clone;
type ConsensusState: ConsensusStateTrait + Into<Any> + TryFrom<Any, Error = ClientError>;
type ConsensusState: ConsensusStateTrait;
}
12 changes: 10 additions & 2 deletions ibc-clients/cw-context/src/context/client_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ use crate::api::ClientType;
use crate::context::CONSENSUS_STATE_HEIGHT_MAP;
use crate::utils::AnyCodec;

impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C> {
impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
type ClientStateRef = C::ClientState;
type ConsensusStateRef = C::ConsensusState;

Expand Down Expand Up @@ -83,7 +87,11 @@ impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C> {
}
}

impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> {
impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
type ClientStateMut = C::ClientState;

fn store_client_state(
Expand Down
7 changes: 6 additions & 1 deletion ibc-clients/cw-context/src/context/custom_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ use ibc_core::client::types::Height;
use ibc_core::handler::types::error::ContextError;
use ibc_core::host::types::identifiers::ClientId;
use ibc_core::host::types::path::ClientConsensusStatePath;
use ibc_core::primitives::proto::Any;
use ibc_core::primitives::Timestamp;

use super::Context;
use crate::api::ClientType;
use crate::types::HeightTravel;

impl<'a, C: ClientType<'a>> ExtClientValidationContext for Context<'a, C> {
impl<'a, C: ClientType<'a>> ExtClientValidationContext for Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
fn host_timestamp(&self) -> Result<Timestamp, ContextError> {
let time = self.env().block.time;

Expand Down
24 changes: 20 additions & 4 deletions ibc-clients/cw-context/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ pub const CONSENSUS_STATE_HEIGHT_MAP: Map<'_, (u64, u64), Empty> =

/// Context is a wrapper around the deps and env that gives access to the
/// methods under the ibc-rs Validation and Execution traits.
pub struct Context<'a, C: ClientType<'a>> {
pub struct Context<'a, C: ClientType<'a>>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
deps: Option<Deps<'a>>,
deps_mut: Option<DepsMut<'a>>,
env: Env,
Expand All @@ -43,7 +47,11 @@ pub struct Context<'a, C: ClientType<'a>> {
client_type: std::marker::PhantomData<C>,
}

impl<'a, C: ClientType<'a>> Context<'a, C> {
impl<'a, C: ClientType<'a>> Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
/// Constructs a new Context object with the given deps and env.
pub fn new_ref(deps: Deps<'a>, env: Env) -> Result<Self, ContractError> {
let client_id = ClientId::from_str(env.contract.address.as_str())?;
Expand Down Expand Up @@ -303,7 +311,11 @@ pub trait StorageRef {
fn storage_ref(&self) -> &dyn Storage;
}

impl<'a, C: ClientType<'a>> StorageRef for Context<'a, C> {
impl<'a, C: ClientType<'a>> StorageRef for Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
fn storage_ref(&self) -> &dyn Storage {
match self.deps {
Some(ref deps) => deps.storage,
Expand All @@ -319,7 +331,11 @@ pub trait StorageMut: StorageRef {
fn storage_mut(&mut self) -> &mut dyn Storage;
}

impl<'a, C: ClientType<'a>> StorageMut for Context<'a, C> {
impl<'a, C: ClientType<'a>> StorageMut for Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
fn storage_mut(&mut self) -> &mut dyn Storage {
match self.deps_mut {
Some(ref mut deps) => deps.storage,
Expand Down
9 changes: 7 additions & 2 deletions ibc-clients/cw-context/src/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use cosmwasm_std::{to_json_binary, Binary};
use ibc_core::client::context::prelude::*;
use ibc_core::client::types::error::ClientError;
use ibc_core::host::types::path::ClientConsensusStatePath;
use ibc_core::primitives::proto::Any;
use prost::Message;
Expand All @@ -13,12 +14,16 @@ use crate::types::{
VerifyUpgradeAndUpdateStateMsg,
};

impl<'a, C: ClientType<'a>> Context<'a, C> {
impl<'a, C: ClientType<'a>> Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Into<ClientError>,
<C::ConsensusState as TryFrom<Any>>::Error: Into<ClientError>,
{
/// Instantiates a new client with the given [`InstantiateMsg`] message.
pub fn instantiate(&mut self, msg: InstantiateMsg) -> Result<Binary, ContractError> {
let any = Any::decode(&mut msg.client_state.as_slice())?;

let client_state = C::ClientState::try_from(any)?;
let client_state = C::ClientState::try_from(any).map_err(Into::into)?;

let any_consensus_state = Any::decode(&mut msg.consensus_state.as_slice())?;

Expand Down
7 changes: 4 additions & 3 deletions ibc-clients/cw-context/src/utils/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ use prost::Message;
pub trait AnyCodec {
fn decode_any_vec<C>(data: Vec<u8>) -> Result<C, ClientError>
where
C: TryFrom<Any, Error = ClientError>,
C: TryFrom<Any>,
<C as TryFrom<Any>>::Error: Into<ClientError>,
{
let raw = Any::decode(&mut data.as_slice()).map_err(|e| ClientError::Other {
description: e.to_string(),
})?;

C::try_from(raw)
C::try_from(raw).map_err(Into::into)
}

fn encode_to_any_vec<C>(value: C) -> Vec<u8>
Expand All @@ -24,4 +25,4 @@ pub trait AnyCodec {
}
}

impl<T> AnyCodec for T where T: TryFrom<Any, Error = ClientError> + Into<Any> {}
impl<T> AnyCodec for T where T: TryFrom<Any> + Into<Any> {}
24 changes: 14 additions & 10 deletions ibc-clients/ics07-tendermint/src/client_state/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ impl<E> ClientStateExecution<E> for ClientState
where
E: ExtClientExecutionContext,
E::ClientStateRef: From<ClientStateType>,
E::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<E::ConsensusStateRef>,
<ConsensusStateType as TryFrom<E::ConsensusStateRef>>::Error: Into<ClientError>,
{
fn initialise(
&self,
Expand Down Expand Up @@ -93,12 +94,12 @@ pub fn initialise<E>(
where
E: ExtClientExecutionContext,
E::ClientStateRef: From<ClientStateType>,
E::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<E::ConsensusStateRef>,
{
let host_timestamp = ExtClientValidationContext::host_timestamp(ctx)?;
let host_height = ExtClientValidationContext::host_height(ctx)?;

let tm_consensus_state = ConsensusStateType::try_from(consensus_state)?;
let tm_consensus_state: ConsensusStateType = consensus_state.try_into()?;

ctx.store_client_state(
ClientStatePath::new(client_id.clone()),
Expand Down Expand Up @@ -138,7 +139,8 @@ pub fn update_state<E>(
where
E: ExtClientExecutionContext,
E::ClientStateRef: From<ClientStateType>,
E::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<E::ConsensusStateRef>,
<ConsensusStateType as TryFrom<E::ConsensusStateRef>>::Error: Into<ClientError>,
{
let header = TmHeader::try_from(header)?;
let header_height = header.height();
Expand Down Expand Up @@ -237,10 +239,10 @@ pub fn update_on_upgrade<E>(
where
E: ExtClientExecutionContext,
E::ClientStateRef: From<ClientStateType>,
E::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<E::ConsensusStateRef>,
{
let mut upgraded_tm_client_state = ClientState::try_from(upgraded_client_state)?;
let upgraded_tm_cons_state = ConsensusStateType::try_from(upgraded_consensus_state)?;
let upgraded_tm_cons_state: ConsensusStateType = upgraded_consensus_state.try_into()?;

upgraded_tm_client_state.0.zero_custom_fields();

Expand Down Expand Up @@ -317,7 +319,8 @@ pub fn prune_oldest_consensus_state<E>(
where
E: ClientExecutionContext + ExtClientValidationContext,
E::ClientStateRef: From<ClientStateType>,
E::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<E::ConsensusStateRef>,
<ConsensusStateType as TryFrom<E::ConsensusStateRef>>::Error: Into<ClientError>,
{
let mut heights = ctx.consensus_state_heights(client_id)?;

Expand All @@ -330,7 +333,8 @@ where
height.revision_height(),
);
let consensus_state = ctx.consensus_state(&client_consensus_state_path)?;
let tm_consensus_state = consensus_state.try_into()?;
let tm_consensus_state: ConsensusStateType =
consensus_state.try_into().map_err(Into::into)?;

let host_timestamp =
ctx.host_timestamp()?
Expand Down Expand Up @@ -380,7 +384,7 @@ pub fn update_on_recovery<E>(
where
E: ExtClientExecutionContext,
E::ClientStateRef: From<ClientStateType>,
E::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<E::ConsensusStateRef>,
{
let substitute_client_state = ClientState::try_from(substitute_client_state)?
.inner()
Expand All @@ -401,7 +405,7 @@ where
let host_timestamp = E::host_timestamp(ctx)?;
let host_height = E::host_height(ctx)?;

let tm_consensus_state = ConsensusStateType::try_from(substitute_consensus_state)?;
let tm_consensus_state: ConsensusStateType = substitute_consensus_state.try_into()?;

ctx.store_consensus_state(
ClientConsensusStatePath::new(
Expand Down
11 changes: 6 additions & 5 deletions ibc-clients/ics07-tendermint/src/client_state/misbehaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,34 @@ pub fn verify_misbehaviour<V, H>(
) -> Result<(), ClientError>
where
V: ExtClientValidationContext,
V::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<V::ConsensusStateRef>,
<ConsensusStateType as TryFrom<V::ConsensusStateRef>>::Error: Into<ClientError>,
H: MerkleHash + Sha256 + Default,
{
misbehaviour.validate_basic::<H>()?;

let header_1 = misbehaviour.header1();
let trusted_consensus_state_1 = {
let trusted_consensus_state_1: ConsensusStateType = {
let consensus_state_path = ClientConsensusStatePath::new(
client_id.clone(),
header_1.trusted_height.revision_number(),
header_1.trusted_height.revision_height(),
);
let consensus_state = ctx.consensus_state(&consensus_state_path)?;

consensus_state.try_into()?
consensus_state.try_into().map_err(Into::into)?
};

let header_2 = misbehaviour.header2();
let trusted_consensus_state_2 = {
let trusted_consensus_state_2: ConsensusStateType = {
let consensus_state_path = ClientConsensusStatePath::new(
client_id.clone(),
header_2.trusted_height.revision_number(),
header_2.trusted_height.revision_height(),
);
let consensus_state = ctx.consensus_state(&consensus_state_path)?;

consensus_state.try_into()?
consensus_state.try_into().map_err(Into::into)?
};

let current_timestamp = ctx.host_timestamp()?;
Expand Down
18 changes: 11 additions & 7 deletions ibc-clients/ics07-tendermint/src/client_state/update_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ pub fn verify_header<V, H>(
) -> Result<(), ClientError>
where
V: ExtClientValidationContext,
V::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<V::ConsensusStateRef>,
<ConsensusStateType as TryFrom<V::ConsensusStateRef>>::Error: Into<ClientError>,
H: MerkleHash + Sha256 + Default,
{
// Checks that the header fields are valid.
Expand All @@ -41,9 +42,10 @@ where
header.trusted_height.revision_number(),
header.trusted_height.revision_height(),
);
let trusted_consensus_state = ctx
let trusted_consensus_state: ConsensusStateType = ctx
.consensus_state(&trusted_client_cons_state_path)?
.try_into()?;
.try_into()
.map_err(Into::into)?;

header.check_trusted_next_validator_set::<H>(
&trusted_consensus_state.next_validators_hash,
Expand Down Expand Up @@ -107,7 +109,8 @@ pub fn check_for_misbehaviour_on_update<V>(
) -> Result<bool, ClientError>
where
V: ExtClientValidationContext,
V::ConsensusStateRef: Convertible<ConsensusStateType, ClientError>,
ConsensusStateType: Convertible<V::ConsensusStateRef>,
<ConsensusStateType as TryFrom<V::ConsensusStateRef>>::Error: Into<ClientError>,
{
let maybe_existing_consensus_state = {
let path_at_header_height = ClientConsensusStatePath::new(
Expand All @@ -120,7 +123,8 @@ where
};

if let Some(existing_consensus_state) = maybe_existing_consensus_state {
let existing_consensus_state = existing_consensus_state.try_into()?;
let existing_consensus_state: ConsensusStateType =
existing_consensus_state.try_into().map_err(Into::into)?;

let header_consensus_state = ConsensusStateType::from(header);

Expand All @@ -138,7 +142,7 @@ where
if let Some(prev_cs) = maybe_prev_cs {
// New header timestamp cannot occur *before* the
// previous consensus state's height
let prev_cs = prev_cs.try_into()?;
let prev_cs: ConsensusStateType = prev_cs.try_into().map_err(Into::into)?;

if header.signed_header.header().time <= prev_cs.timestamp() {
return Ok(true);
Expand All @@ -154,7 +158,7 @@ where
if let Some(next_cs) = maybe_next_cs {
// New (untrusted) header timestamp cannot occur *after* next
// consensus state's height
let next_cs = next_cs.try_into()?;
let next_cs: ConsensusStateType = next_cs.try_into().map_err(Into::into)?;

if header.signed_header.header().time >= next_cs.timestamp() {
return Ok(true);
Expand Down
Loading

0 comments on commit dc116da

Please sign in to comment.