From b02bedd6757ec3bdb6f487b7dea92207a2cf5c87 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 1 Feb 2023 12:12:38 +0100 Subject: [PATCH 1/4] Add draft work for ibc-framework --- Cargo.lock | 7 + Cargo.toml | 1 + crates/ibc-framework/Cargo.toml | 21 ++ .../all_for_one/instances/message_handlers.rs | 22 ++ .../src/all_for_one/instances/mod.rs | 1 + crates/ibc-framework/src/all_for_one/mod.rs | 2 + .../src/all_for_one/traits/base.rs | 44 ++++ .../src/all_for_one/traits/error.rs | 15 ++ .../src/all_for_one/traits/event.rs | 9 + .../src/all_for_one/traits/mod.rs | 3 + .../ibc-framework/src/core/aliases/client.rs | 15 ++ crates/ibc-framework/src/core/aliases/ibc.rs | 8 + crates/ibc-framework/src/core/aliases/mod.rs | 2 + .../src/core/impls/client_reader.rs | 83 ++++++++ .../src/core/impls/handlers/mod.rs | 1 + .../impls/handlers/update_client/combine.rs | 46 ++++ .../core/impls/handlers/update_client/lift.rs | 47 +++++ .../core/impls/handlers/update_client/mod.rs | 2 + .../core/impls/message_handlers/dispatch.rs | 38 ++++ .../src/core/impls/message_handlers/mod.rs | 2 + .../impls/message_handlers/update_client.rs | 108 ++++++++++ crates/ibc-framework/src/core/impls/mod.rs | 3 + crates/ibc-framework/src/core/mod.rs | 3 + .../ibc-framework/src/core/traits/client.rs | 199 ++++++++++++++++++ crates/ibc-framework/src/core/traits/error.rs | 9 + crates/ibc-framework/src/core/traits/event.rs | 9 + .../src/core/traits/events/misbehavior.rs | 15 ++ .../src/core/traits/events/mod.rs | 2 + .../src/core/traits/events/update_client.rs | 15 ++ .../src/core/traits/handlers/mod.rs | 1 + .../src/core/traits/handlers/update_client.rs | 49 +++++ crates/ibc-framework/src/core/traits/host.rs | 18 ++ crates/ibc-framework/src/core/traits/ibc.rs | 13 ++ .../ibc-framework/src/core/traits/message.rs | 13 ++ .../src/core/traits/message_handler.rs | 9 + .../src/core/traits/messages/ibc.rs | 5 + .../src/core/traits/messages/mod.rs | 2 + .../src/core/traits/messages/update_client.rs | 40 ++++ crates/ibc-framework/src/core/traits/mod.rs | 13 ++ crates/ibc-framework/src/core/traits/prism.rs | 9 + .../src/core/traits/stores/client_reader.rs | 172 +++++++++++++++ .../src/core/traits/stores/client_writer.rs | 40 ++++ .../src/core/traits/stores/kvstore.rs | 20 ++ .../src/core/traits/stores/mod.rs | 3 + crates/ibc-framework/src/core/traits/sync.rs | 3 + crates/ibc-framework/src/lib.rs | 11 + .../src/one_for_all/components/default.rs | 18 ++ .../src/one_for_all/components/mod.rs | 1 + .../src/one_for_all/impls/chain.rs | 162 ++++++++++++++ .../src/one_for_all/impls/components.rs | 41 ++++ .../src/one_for_all/impls/error.rs | 44 ++++ .../src/one_for_all/impls/event.rs | 32 +++ .../src/one_for_all/impls/mod.rs | 5 + .../src/one_for_all/impls/stores.rs | 86 ++++++++ .../src/one_for_all/instances/chain.rs | 13 ++ .../src/one_for_all/instances/mod.rs | 1 + crates/ibc-framework/src/one_for_all/mod.rs | 5 + .../src/one_for_all/traits/chain.rs | 171 +++++++++++++++ .../src/one_for_all/traits/components.rs | 24 +++ .../src/one_for_all/traits/mod.rs | 2 + .../src/one_for_all/types/chain.rs | 4 + .../src/one_for_all/types/mod.rs | 1 + crates/ibc-framework/src/std_prelude.rs | 15 ++ 63 files changed, 1778 insertions(+) create mode 100644 crates/ibc-framework/Cargo.toml create mode 100644 crates/ibc-framework/src/all_for_one/instances/message_handlers.rs create mode 100644 crates/ibc-framework/src/all_for_one/instances/mod.rs create mode 100644 crates/ibc-framework/src/all_for_one/mod.rs create mode 100644 crates/ibc-framework/src/all_for_one/traits/base.rs create mode 100644 crates/ibc-framework/src/all_for_one/traits/error.rs create mode 100644 crates/ibc-framework/src/all_for_one/traits/event.rs create mode 100644 crates/ibc-framework/src/all_for_one/traits/mod.rs create mode 100644 crates/ibc-framework/src/core/aliases/client.rs create mode 100644 crates/ibc-framework/src/core/aliases/ibc.rs create mode 100644 crates/ibc-framework/src/core/aliases/mod.rs create mode 100644 crates/ibc-framework/src/core/impls/client_reader.rs create mode 100644 crates/ibc-framework/src/core/impls/handlers/mod.rs create mode 100644 crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs create mode 100644 crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs create mode 100644 crates/ibc-framework/src/core/impls/handlers/update_client/mod.rs create mode 100644 crates/ibc-framework/src/core/impls/message_handlers/dispatch.rs create mode 100644 crates/ibc-framework/src/core/impls/message_handlers/mod.rs create mode 100644 crates/ibc-framework/src/core/impls/message_handlers/update_client.rs create mode 100644 crates/ibc-framework/src/core/impls/mod.rs create mode 100644 crates/ibc-framework/src/core/mod.rs create mode 100644 crates/ibc-framework/src/core/traits/client.rs create mode 100644 crates/ibc-framework/src/core/traits/error.rs create mode 100644 crates/ibc-framework/src/core/traits/event.rs create mode 100644 crates/ibc-framework/src/core/traits/events/misbehavior.rs create mode 100644 crates/ibc-framework/src/core/traits/events/mod.rs create mode 100644 crates/ibc-framework/src/core/traits/events/update_client.rs create mode 100644 crates/ibc-framework/src/core/traits/handlers/mod.rs create mode 100644 crates/ibc-framework/src/core/traits/handlers/update_client.rs create mode 100644 crates/ibc-framework/src/core/traits/host.rs create mode 100644 crates/ibc-framework/src/core/traits/ibc.rs create mode 100644 crates/ibc-framework/src/core/traits/message.rs create mode 100644 crates/ibc-framework/src/core/traits/message_handler.rs create mode 100644 crates/ibc-framework/src/core/traits/messages/ibc.rs create mode 100644 crates/ibc-framework/src/core/traits/messages/mod.rs create mode 100644 crates/ibc-framework/src/core/traits/messages/update_client.rs create mode 100644 crates/ibc-framework/src/core/traits/mod.rs create mode 100644 crates/ibc-framework/src/core/traits/prism.rs create mode 100644 crates/ibc-framework/src/core/traits/stores/client_reader.rs create mode 100644 crates/ibc-framework/src/core/traits/stores/client_writer.rs create mode 100644 crates/ibc-framework/src/core/traits/stores/kvstore.rs create mode 100644 crates/ibc-framework/src/core/traits/stores/mod.rs create mode 100644 crates/ibc-framework/src/core/traits/sync.rs create mode 100644 crates/ibc-framework/src/lib.rs create mode 100644 crates/ibc-framework/src/one_for_all/components/default.rs create mode 100644 crates/ibc-framework/src/one_for_all/components/mod.rs create mode 100644 crates/ibc-framework/src/one_for_all/impls/chain.rs create mode 100644 crates/ibc-framework/src/one_for_all/impls/components.rs create mode 100644 crates/ibc-framework/src/one_for_all/impls/error.rs create mode 100644 crates/ibc-framework/src/one_for_all/impls/event.rs create mode 100644 crates/ibc-framework/src/one_for_all/impls/mod.rs create mode 100644 crates/ibc-framework/src/one_for_all/impls/stores.rs create mode 100644 crates/ibc-framework/src/one_for_all/instances/chain.rs create mode 100644 crates/ibc-framework/src/one_for_all/instances/mod.rs create mode 100644 crates/ibc-framework/src/one_for_all/mod.rs create mode 100644 crates/ibc-framework/src/one_for_all/traits/chain.rs create mode 100644 crates/ibc-framework/src/one_for_all/traits/components.rs create mode 100644 crates/ibc-framework/src/one_for_all/traits/mod.rs create mode 100644 crates/ibc-framework/src/one_for_all/types/chain.rs create mode 100644 crates/ibc-framework/src/one_for_all/types/mod.rs create mode 100644 crates/ibc-framework/src/std_prelude.rs diff --git a/Cargo.lock b/Cargo.lock index 541b23ae49..e4b8c19b1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,6 +1751,13 @@ dependencies = [ "tracing", ] +[[package]] +name = "ibc-framework" +version = "0.1.0" +dependencies = [ + "async-trait", +] + [[package]] name = "ibc-integration-test" version = "0.21.0" diff --git a/Cargo.toml b/Cargo.toml index d23be53764..0e28fc3484 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "crates/relayer-framework-test", "crates/relayer-runtime", "crates/relayer-cosmos", + "crates/ibc-framework", "crates/telemetry", "crates/chain-registry", "tools/integration-test", diff --git a/crates/ibc-framework/Cargo.toml b/crates/ibc-framework/Cargo.toml new file mode 100644 index 0000000000..7548a53ae7 --- /dev/null +++ b/crates/ibc-framework/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ibc-framework" +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +readme = "README.md" +keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] +repository = "https://github.com/informalsystems/ibc-rs" +authors = ["Informal Systems "] +rust-version = "1.60" +description = """ + Implementation of an IBC Relayer in Rust, as a library +""" + +[package.metadata.docs.rs] +all-features = true + +[features] + +[dependencies] +async-trait = "0.1.56" diff --git a/crates/ibc-framework/src/all_for_one/instances/message_handlers.rs b/crates/ibc-framework/src/all_for_one/instances/message_handlers.rs new file mode 100644 index 0000000000..7899a4d9ae --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/instances/message_handlers.rs @@ -0,0 +1,22 @@ +use core::marker::PhantomData; + +use crate::all_for_one::traits::base::AfoChainContext; +use crate::core::impls::message_handlers::dispatch::DispatchIbcMessages; +use crate::core::impls::message_handlers::update_client::BaseUpdateClientMessageHandler; +use crate::core::traits::message_handler::MessageHandler; +use crate::core::traits::messages::update_client::UpdateClientMessageHandler; + +pub fn can_build_base_update_client_message_handler( +) -> PhantomData> +where + Context: AfoChainContext, +{ + PhantomData:: +} + +pub fn can_build_dispatch_ibc_message_handler() -> PhantomData> +where + Context: AfoChainContext, +{ + PhantomData:: +} diff --git a/crates/ibc-framework/src/all_for_one/instances/mod.rs b/crates/ibc-framework/src/all_for_one/instances/mod.rs new file mode 100644 index 0000000000..ca6ee17501 --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/instances/mod.rs @@ -0,0 +1 @@ +pub mod message_handlers; diff --git a/crates/ibc-framework/src/all_for_one/mod.rs b/crates/ibc-framework/src/all_for_one/mod.rs new file mode 100644 index 0000000000..850a32dc03 --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/mod.rs @@ -0,0 +1,2 @@ +pub mod instances; +pub mod traits; diff --git a/crates/ibc-framework/src/all_for_one/traits/base.rs b/crates/ibc-framework/src/all_for_one/traits/base.rs new file mode 100644 index 0000000000..db8cf051b8 --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/traits/base.rs @@ -0,0 +1,44 @@ +use crate::all_for_one::traits::error::AfoErrorContext; +use crate::all_for_one::traits::event::AfoEventContext; +use crate::core::traits::client::HasAnyClientMethods; +use crate::core::traits::event::HasEventEmitter; +use crate::core::traits::handlers::update_client::HasAnyUpdateClientHandler; +use crate::core::traits::host::HasHostMethods; +use crate::core::traits::ibc::HasIbcTypes; +use crate::core::traits::message::HasMessageMethods; +use crate::core::traits::messages::ibc::HasIbcMessages; +use crate::core::traits::messages::update_client::HasUpdateClientMessageHandler; +use crate::core::traits::stores::client_reader::HasAnyClientReader; +use crate::core::traits::stores::client_writer::HasAnyClientWriter; + +pub trait AfoChainContext: + AfoErrorContext + + AfoEventContext + + HasIbcTypes + + HasMessageMethods + + HasAnyClientMethods + + HasAnyClientReader + + HasAnyClientWriter + + HasAnyUpdateClientHandler + + HasHostMethods + + HasIbcMessages + + HasEventEmitter + + HasUpdateClientMessageHandler +{ +} + +impl AfoChainContext for Context where + Context: AfoErrorContext + + AfoEventContext + + HasIbcTypes + + HasMessageMethods + + HasAnyClientMethods + + HasAnyClientReader + + HasAnyClientWriter + + HasAnyUpdateClientHandler + + HasHostMethods + + HasIbcMessages + + HasEventEmitter + + HasUpdateClientMessageHandler +{ +} diff --git a/crates/ibc-framework/src/all_for_one/traits/error.rs b/crates/ibc-framework/src/all_for_one/traits/error.rs new file mode 100644 index 0000000000..9c9f5f6308 --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/traits/error.rs @@ -0,0 +1,15 @@ +use crate::core::impls::message_handlers::dispatch::InjectDispatchError; +use crate::core::impls::message_handlers::update_client::InjectUpdateClientError; +use crate::core::traits::client::InjectClientTypeMismatchError; +use crate::core::traits::error::HasError; + +pub trait AfoErrorContext: + HasError + InjectClientTypeMismatchError + InjectDispatchError + InjectUpdateClientError +{ +} + +impl AfoErrorContext for Context where + Context: + HasError + InjectClientTypeMismatchError + InjectDispatchError + InjectUpdateClientError +{ +} diff --git a/crates/ibc-framework/src/all_for_one/traits/event.rs b/crates/ibc-framework/src/all_for_one/traits/event.rs new file mode 100644 index 0000000000..0b19043168 --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/traits/event.rs @@ -0,0 +1,9 @@ +use crate::core::traits::events::misbehavior::InjectMisbehaviorEvent; +use crate::core::traits::events::update_client::InjectUpdateClientEvent; + +pub trait AfoEventContext: InjectUpdateClientEvent + InjectMisbehaviorEvent {} + +impl AfoEventContext for Context where + Context: InjectUpdateClientEvent + InjectMisbehaviorEvent +{ +} diff --git a/crates/ibc-framework/src/all_for_one/traits/mod.rs b/crates/ibc-framework/src/all_for_one/traits/mod.rs new file mode 100644 index 0000000000..b25d9ce4ab --- /dev/null +++ b/crates/ibc-framework/src/all_for_one/traits/mod.rs @@ -0,0 +1,3 @@ +pub mod base; +pub mod error; +pub mod event; diff --git a/crates/ibc-framework/src/core/aliases/client.rs b/crates/ibc-framework/src/core/aliases/client.rs new file mode 100644 index 0000000000..dbfd35b9d6 --- /dev/null +++ b/crates/ibc-framework/src/core/aliases/client.rs @@ -0,0 +1,15 @@ +use crate::core::traits::client::{HasAnyClientTypes, HasClientTypes}; + +pub type ClientType = ::ClientType; + +pub type AnyClientState = ::AnyClientState; + +pub type ClientState = ::ClientState; + +pub type AnyConsensusState = ::AnyConsensusState; + +pub type ConsensusState = ::ConsensusState; + +pub type AnyClientHeader = ::AnyClientHeader; + +pub type ClientHeader = ::ClientHeader; diff --git a/crates/ibc-framework/src/core/aliases/ibc.rs b/crates/ibc-framework/src/core/aliases/ibc.rs new file mode 100644 index 0000000000..779f4c2aad --- /dev/null +++ b/crates/ibc-framework/src/core/aliases/ibc.rs @@ -0,0 +1,8 @@ +use crate::core::traits::host::HasHostTypes; +use crate::core::traits::ibc::HasIbcTypes; + +pub type Height = ::Height; + +pub type Timestamp = ::Timestamp; + +pub type ClientId = ::ClientId; diff --git a/crates/ibc-framework/src/core/aliases/mod.rs b/crates/ibc-framework/src/core/aliases/mod.rs new file mode 100644 index 0000000000..d0dc4e23a0 --- /dev/null +++ b/crates/ibc-framework/src/core/aliases/mod.rs @@ -0,0 +1,2 @@ +pub mod client; +pub mod ibc; diff --git a/crates/ibc-framework/src/core/impls/client_reader.rs b/crates/ibc-framework/src/core/impls/client_reader.rs new file mode 100644 index 0000000000..274a87904a --- /dev/null +++ b/crates/ibc-framework/src/core/impls/client_reader.rs @@ -0,0 +1,83 @@ +use crate::core::traits::client::{ContainsClient, HasClientTypeFor, HasClientTypes}; +use crate::core::traits::stores::client_reader::{ClientReader, HasAnyClientReader}; + +pub struct ClientReaderFromAnyClient; + +impl ClientReader for ClientReaderFromAnyClient +where + Client: HasClientTypes, + Context: HasAnyClientReader + ContainsClient + HasClientTypeFor, +{ + fn get_client_state( + context: &Context, + client_id: &Context::ClientId, + ) -> Result { + let any_client_state = context.get_any_client_state(client_id)?; + + let client_state = Context::try_from_any_client_state(any_client_state)?; + + Ok(client_state) + } + + fn get_latest_consensus_state( + context: &Context, + client_id: &Context::ClientId, + ) -> Result { + let any_consensus_state = context.get_latest_any_consensus_state(client_id)?; + + let consensus_state = Context::try_from_any_consensus_state(any_consensus_state)?; + + Ok(consensus_state) + } + + fn get_consensus_state_at_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error> { + let m_consensus_state = context.get_any_consensus_state_at_height(client_id, height)?; + + match m_consensus_state { + Some(any_consensus_state) => { + let consensus_state = Context::try_from_any_consensus_state(any_consensus_state)?; + + Ok(Some(consensus_state)) + } + None => Ok(None), + } + } + + fn get_consensus_state_after_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error> { + let m_consensus_state = context.get_any_consensus_state_after_height(client_id, height)?; + + match m_consensus_state { + Some(any_consensus_state) => { + let consensus_state = Context::try_from_any_consensus_state(any_consensus_state)?; + + Ok(Some(consensus_state)) + } + None => Ok(None), + } + } + + fn get_consensus_state_before_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error> { + let m_consensus_state = context.get_any_consensus_state_before_height(client_id, height)?; + + match m_consensus_state { + Some(any_consensus_state) => { + let consensus_state = Context::try_from_any_consensus_state(any_consensus_state)?; + + Ok(Some(consensus_state)) + } + None => Ok(None), + } + } +} diff --git a/crates/ibc-framework/src/core/impls/handlers/mod.rs b/crates/ibc-framework/src/core/impls/handlers/mod.rs new file mode 100644 index 0000000000..4a9b38e378 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/handlers/mod.rs @@ -0,0 +1 @@ +pub mod update_client; diff --git a/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs b/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs new file mode 100644 index 0000000000..c03b1c1e98 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs @@ -0,0 +1,46 @@ +use core::marker::PhantomData; + +use crate::core::impls::handlers::update_client::lift::LiftClientUpdateHandler; +use crate::core::traits::client::{ContainsClient, HasClientTypes}; +use crate::core::traits::handlers::update_client::{AnyUpdateClientHandler, UpdateClientHandler}; +use crate::core::traits::stores::client_reader::HasAnyClientReader; + +pub struct CombineClientUpdateHandler( + pub PhantomData<(Handler, NextHandlers)>, +); + +impl AnyUpdateClientHandler + for CombineClientUpdateHandler +where + Context: HasAnyClientReader, + Context: ContainsClient, + Client: HasClientTypes, + Handler: UpdateClientHandler, + NextHandlers: AnyUpdateClientHandler, + LiftClientUpdateHandler: AnyUpdateClientHandler, +{ + fn check_client_header_and_update_state( + context: &Context, + client_id: &Context::ClientId, + client_state: &Context::AnyClientState, + new_client_header: &Context::AnyClientHeader, + ) -> Result<(Context::AnyClientState, Context::AnyConsensusState), Context::Error> { + let client_type = context.get_client_type(client_id)?; + + if client_type == Context::CLIENT_TYPE { + >::check_client_header_and_update_state( + context, + client_id, + client_state, + new_client_header, + ) + } else { + NextHandlers::check_client_header_and_update_state( + context, + client_id, + client_state, + new_client_header, + ) + } + } +} diff --git a/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs b/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs new file mode 100644 index 0000000000..adeb43beaa --- /dev/null +++ b/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs @@ -0,0 +1,47 @@ +use core::marker::PhantomData; + +use crate::core::traits::client::{ + ContainsClient, HasAnyClientMethods, HasClientTypes, InjectClientTypeMismatchError, +}; +use crate::core::traits::error::HasError; +use crate::core::traits::handlers::update_client::{AnyUpdateClientHandler, UpdateClientHandler}; +use crate::core::traits::ibc::HasIbcTypes; + +pub struct LiftClientUpdateHandler(pub PhantomData); + +impl AnyUpdateClientHandler for LiftClientUpdateHandler +where + Context: HasError + HasIbcTypes + HasAnyClientMethods, + Context: ContainsClient, + Client: HasClientTypes, + Handler: UpdateClientHandler, + Context: InjectClientTypeMismatchError, +{ + fn check_client_header_and_update_state( + context: &Context, + client_id: &Context::ClientId, + client_state: &Context::AnyClientState, + new_client_header: &Context::AnyClientHeader, + ) -> Result<(Context::AnyClientState, Context::AnyConsensusState), Context::Error> { + let client_type = Context::client_state_type(client_state); + + if client_type != Context::CLIENT_TYPE {} + + let client_state = Context::try_from_any_client_state_ref(client_state)?; + + let client_header = Context::try_from_any_client_header_ref(new_client_header)?; + + let (new_client_state, new_consensus_state) = + Handler::check_client_header_and_update_state( + context, + client_id, + client_state, + client_header, + )?; + + Ok(( + Context::into_any_client_state(new_client_state), + Context::into_any_consensus_state(new_consensus_state), + )) + } +} diff --git a/crates/ibc-framework/src/core/impls/handlers/update_client/mod.rs b/crates/ibc-framework/src/core/impls/handlers/update_client/mod.rs new file mode 100644 index 0000000000..605ec430e4 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/handlers/update_client/mod.rs @@ -0,0 +1,2 @@ +pub mod combine; +pub mod lift; diff --git a/crates/ibc-framework/src/core/impls/message_handlers/dispatch.rs b/crates/ibc-framework/src/core/impls/message_handlers/dispatch.rs new file mode 100644 index 0000000000..bce3f86955 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/message_handlers/dispatch.rs @@ -0,0 +1,38 @@ +use crate::core::traits::error::HasError; +use crate::core::traits::message::HasMessageMethods; +use crate::core::traits::message_handler::MessageHandler; +use crate::core::traits::messages::update_client::{ + HasUpdateClientMessage, HasUpdateClientMessageHandler, +}; + +pub struct DispatchIbcMessages; + +pub trait InjectDispatchError: HasMessageMethods + HasError { + fn unknown_message_error(message_type: &Self::MessageType) -> Self::Error; + + fn parse_message_error(message_type: &Self::MessageType) -> Self::Error; +} + +impl MessageHandler for DispatchIbcMessages +where + Context: HasMessageMethods, + Context: HasUpdateClientMessageHandler, + Context: InjectDispatchError, +{ + fn handle_message(context: &Context, message: &Context::Message) -> Result<(), Context::Error> { + let message_type = Context::message_type(message); + + // TODO: Handle all IBC messages here + + if message_type == ::MESSAGE_TYPE { + let update_client_message = Context::try_extract_update_client_message(message) + .ok_or_else(|| Context::parse_message_error(&message_type))?; + + context.handle_update_client_message(update_client_message)?; + + Ok(()) + } else { + Err(Context::unknown_message_error(&message_type)) + } + } +} diff --git a/crates/ibc-framework/src/core/impls/message_handlers/mod.rs b/crates/ibc-framework/src/core/impls/message_handlers/mod.rs new file mode 100644 index 0000000000..5f5a4c3618 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/message_handlers/mod.rs @@ -0,0 +1,2 @@ +pub mod dispatch; +pub mod update_client; diff --git a/crates/ibc-framework/src/core/impls/message_handlers/update_client.rs b/crates/ibc-framework/src/core/impls/message_handlers/update_client.rs new file mode 100644 index 0000000000..b9aab2f0d5 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/message_handlers/update_client.rs @@ -0,0 +1,108 @@ +use crate::core::traits::client::HasAnyClientMethods; +use crate::core::traits::error::HasError; +use crate::core::traits::event::HasEventEmitter; +use crate::core::traits::events::misbehavior::InjectMisbehaviorEvent; +use crate::core::traits::events::update_client::InjectUpdateClientEvent; +use crate::core::traits::handlers::update_client::HasAnyUpdateClientHandler; +use crate::core::traits::host::{HasHostMethods, HasHostTypes}; +use crate::core::traits::ibc::HasIbcTypes; +use crate::core::traits::messages::update_client::{ + HasUpdateClientMessage, UpdateClientMessageHandler, +}; +use crate::core::traits::stores::client_reader::HasAnyClientReader; +use crate::core::traits::stores::client_writer::HasAnyClientWriter; + +pub trait InjectUpdateClientError: HasError + HasIbcTypes + HasHostTypes { + fn client_frozen_error(client_id: &Self::ClientId) -> Self::Error; + + fn client_expired_error( + client_id: &Self::ClientId, + current_time: &Self::Timestamp, + latest_allowed_update_time: &Self::Timestamp, + ) -> Self::Error; +} + +pub struct BaseUpdateClientMessageHandler; + +impl UpdateClientMessageHandler for BaseUpdateClientMessageHandler +where + Context: HasUpdateClientMessage, + Context: HasAnyClientReader, + Context: HasAnyUpdateClientHandler, + Context: HasAnyClientMethods, + Context: InjectUpdateClientError, + Context: HasHostMethods, + Context: HasIbcTypes, + Context: InjectUpdateClientEvent, + Context: InjectMisbehaviorEvent, + Context: HasEventEmitter, + Context: HasAnyClientWriter, +{ + fn handle_update_client_message( + context: &Context, + message: &Context::UpdateClientMessage, + ) -> Result<(), Context::Error> { + let client_id = Context::message_client_id(message); + let new_any_client_header = Context::message_client_header(message); + + let current_any_client_state = context.get_any_client_state(client_id)?; + + if Context::client_state_is_frozen(¤t_any_client_state) { + return Err(Context::client_frozen_error(client_id)); + } + + { + let current_time = context.host_timestamp(); + + let latest_consensus_state = context.get_latest_any_consensus_state(client_id)?; + + let last_updated_time = Context::consensus_state_timestamp(&latest_consensus_state); + + let trusting_period = Context::client_state_trusting_period(¤t_any_client_state); + + let latest_allowed_update_time = + Context::add_duration(&last_updated_time, &trusting_period); + + if current_time > latest_allowed_update_time { + return Err(Context::client_expired_error( + client_id, + ¤t_time, + &latest_allowed_update_time, + )); + } + } + + let (new_any_client_state, new_any_consensus_state) = context + .check_client_header_and_update_state( + client_id, + ¤t_any_client_state, + new_any_client_header, + )?; + + context.set_any_client_state(client_id, &new_any_client_state)?; + + if Context::client_state_is_frozen(&new_any_client_state) { + let event = Context::misbehavior_event( + client_id, + &Context::client_state_type(&new_any_client_state), + &Context::client_header_height(new_any_client_header), + new_any_client_header, + ); + + context.emit_event(&event); + } else { + context.set_any_consensus_state(client_id, &new_any_consensus_state)?; + + let event = Context::update_client_event( + client_id, + &Context::client_state_type(&new_any_client_state), + &Context::client_header_height(new_any_client_header), + new_any_client_header, + ); + + context.emit_event(&event); + } + + Ok(()) + } +} diff --git a/crates/ibc-framework/src/core/impls/mod.rs b/crates/ibc-framework/src/core/impls/mod.rs new file mode 100644 index 0000000000..bf5a957d45 --- /dev/null +++ b/crates/ibc-framework/src/core/impls/mod.rs @@ -0,0 +1,3 @@ +pub mod client_reader; +pub mod handlers; +pub mod message_handlers; diff --git a/crates/ibc-framework/src/core/mod.rs b/crates/ibc-framework/src/core/mod.rs new file mode 100644 index 0000000000..ac498e78a0 --- /dev/null +++ b/crates/ibc-framework/src/core/mod.rs @@ -0,0 +1,3 @@ +pub mod aliases; +pub mod impls; +pub mod traits; diff --git a/crates/ibc-framework/src/core/traits/client.rs b/crates/ibc-framework/src/core/traits/client.rs new file mode 100644 index 0000000000..daae8ca975 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/client.rs @@ -0,0 +1,199 @@ +use crate::core::traits::error::HasError; +use crate::core::traits::host::HasHostTypes; +use crate::core::traits::prism::Prism; +use crate::core::traits::sync::Async; + +pub trait HasAnyClientTypes: Async { + type ClientType: Eq + Async; + + type AnyClientState: Async; + + type AnyConsensusState: Async; + + type AnyClientHeader: Async; + + type AnyMisbehavior: Async; +} + +pub trait HasAnyClientMethods: HasAnyClientTypes + HasHostTypes { + fn client_state_type(client_state: &Self::AnyClientState) -> Self::ClientType; + + fn client_state_is_frozen(client_state: &Self::AnyClientState) -> bool; + + fn client_state_trusting_period(client_state: &Self::AnyClientState) -> Self::Duration; + + fn client_state_latest_height(client_state: &Self::AnyClientState) -> Self::Height; + + fn consensus_state_timestamp(consensus_state: &Self::AnyConsensusState) -> Self::Timestamp; + + fn client_header_height(client_header: &Self::AnyClientHeader) -> Self::Height; +} + +pub trait HasClientTypes: Async { + type ClientState: Async; + + type ConsensusState: Async; + + type ClientHeader: Async; + + type Misbehavior: Async; +} + +pub trait HasClientTypeFor: HasAnyClientTypes { + const CLIENT_TYPE: Self::ClientType; +} + +pub trait InjectClientTypeMismatchError: HasError + HasAnyClientTypes { + fn client_type_mismatch_error(expected_client_type: &Self::ClientType) -> Self::Error; +} + +pub trait HasClientPrisms: + HasAnyClientTypes + + Prism + + Prism + + Prism + + Prism + + HasError +where + Client: HasClientTypes, +{ + fn into_any_client_state(client_state: Client::ClientState) -> Self::AnyClientState; + + fn try_from_any_client_state( + client_state: Self::AnyClientState, + ) -> Result; + + fn try_from_any_client_state_ref( + client_state: &Self::AnyClientState, + ) -> Result<&Client::ClientState, Self::Error>; + + fn into_any_consensus_state(consensus_state: Client::ConsensusState) + -> Self::AnyConsensusState; + + fn try_from_any_consensus_state( + consensus_state: Self::AnyConsensusState, + ) -> Result; + + fn try_from_any_consensus_state_ref( + consensus_state: &Self::AnyConsensusState, + ) -> Result<&Client::ConsensusState, Self::Error>; + + fn into_any_client_header(client_header: Client::ClientHeader) -> Self::AnyClientHeader; + + fn try_from_any_client_header( + client_header: Self::AnyClientHeader, + ) -> Result; + + fn try_from_any_client_header_ref( + client_header: &Self::AnyClientHeader, + ) -> Result<&Client::ClientHeader, Self::Error>; + + fn into_any_misbehavior(misbehavior: Client::Misbehavior) -> Self::AnyMisbehavior; + + fn try_from_any_misbehavior( + misbehavior: Self::AnyMisbehavior, + ) -> Result; + + fn try_from_any_misbehavior_ref( + misbehavior: &Self::AnyMisbehavior, + ) -> Result<&Client::Misbehavior, Self::Error>; +} + +impl HasClientPrisms for Context +where + Context: HasClientTypeFor, + Client: HasClientTypes, + Context: InjectClientTypeMismatchError, + Context: Prism + + Prism + + Prism + + Prism, +{ + fn into_any_client_state(client_state: Client::ClientState) -> Self::AnyClientState { + Context::into(client_state) + } + + fn try_from_any_client_state( + client_state: Self::AnyClientState, + ) -> Result { + Context::try_from(client_state) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn try_from_any_client_state_ref( + client_state: &Self::AnyClientState, + ) -> Result<&Client::ClientState, Context::Error> { + Context::try_from_ref(client_state) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn into_any_consensus_state( + consensus_state: Client::ConsensusState, + ) -> Self::AnyConsensusState { + Context::into(consensus_state) + } + + fn try_from_any_consensus_state( + consensus_state: Self::AnyConsensusState, + ) -> Result { + Context::try_from(consensus_state) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn try_from_any_consensus_state_ref( + consensus_state: &Self::AnyConsensusState, + ) -> Result<&Client::ConsensusState, Context::Error> { + Context::try_from_ref(consensus_state) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn into_any_client_header(client_header: Client::ClientHeader) -> Self::AnyClientHeader { + Context::into(client_header) + } + + fn try_from_any_client_header( + client_header: Self::AnyClientHeader, + ) -> Result { + Context::try_from(client_header) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn try_from_any_client_header_ref( + client_header: &Self::AnyClientHeader, + ) -> Result<&Client::ClientHeader, Context::Error> { + Context::try_from_ref(client_header) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn into_any_misbehavior(misbehavior: Client::Misbehavior) -> Self::AnyMisbehavior { + Context::into(misbehavior) + } + + fn try_from_any_misbehavior( + misbehavior: Self::AnyMisbehavior, + ) -> Result { + Context::try_from(misbehavior) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } + + fn try_from_any_misbehavior_ref( + misbehavior: &Self::AnyMisbehavior, + ) -> Result<&Client::Misbehavior, Context::Error> { + Context::try_from_ref(misbehavior) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + } +} + +pub trait ContainsClient: + HasAnyClientTypes + HasClientPrisms + HasClientTypeFor +where + Client: HasClientTypes, +{ +} + +impl ContainsClient for Context +where + Client: HasClientTypes, + Context: HasAnyClientTypes + HasClientPrisms + HasClientTypeFor, +{ +} diff --git a/crates/ibc-framework/src/core/traits/error.rs b/crates/ibc-framework/src/core/traits/error.rs new file mode 100644 index 0000000000..2291d07ceb --- /dev/null +++ b/crates/ibc-framework/src/core/traits/error.rs @@ -0,0 +1,9 @@ +use crate::core::traits::sync::Async; + +pub trait HasError: Async { + type Error: Async; +} + +pub trait InjectError: HasError { + fn inject_error(error: E) -> Self::Error; +} diff --git a/crates/ibc-framework/src/core/traits/event.rs b/crates/ibc-framework/src/core/traits/event.rs new file mode 100644 index 0000000000..c2051f7b19 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/event.rs @@ -0,0 +1,9 @@ +use crate::core::traits::sync::Async; + +pub trait HasEventTypes: Async { + type Event: Async; +} + +pub trait HasEventEmitter: HasEventTypes { + fn emit_event(&self, event: &Self::Event); +} diff --git a/crates/ibc-framework/src/core/traits/events/misbehavior.rs b/crates/ibc-framework/src/core/traits/events/misbehavior.rs new file mode 100644 index 0000000000..b2402a98ef --- /dev/null +++ b/crates/ibc-framework/src/core/traits/events/misbehavior.rs @@ -0,0 +1,15 @@ +use crate::core::traits::client::HasAnyClientTypes; +use crate::core::traits::event::HasEventTypes; +use crate::core::traits::host::HasHostTypes; +use crate::core::traits::ibc::HasIbcTypes; + +pub trait InjectMisbehaviorEvent: + HasAnyClientTypes + HasEventTypes + HasIbcTypes + HasHostTypes +{ + fn misbehavior_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event; +} diff --git a/crates/ibc-framework/src/core/traits/events/mod.rs b/crates/ibc-framework/src/core/traits/events/mod.rs new file mode 100644 index 0000000000..b896562cab --- /dev/null +++ b/crates/ibc-framework/src/core/traits/events/mod.rs @@ -0,0 +1,2 @@ +pub mod misbehavior; +pub mod update_client; diff --git a/crates/ibc-framework/src/core/traits/events/update_client.rs b/crates/ibc-framework/src/core/traits/events/update_client.rs new file mode 100644 index 0000000000..00fd15d39c --- /dev/null +++ b/crates/ibc-framework/src/core/traits/events/update_client.rs @@ -0,0 +1,15 @@ +use crate::core::traits::client::HasAnyClientTypes; +use crate::core::traits::event::HasEventTypes; +use crate::core::traits::host::HasHostTypes; +use crate::core::traits::ibc::HasIbcTypes; + +pub trait InjectUpdateClientEvent: + HasAnyClientTypes + HasEventTypes + HasIbcTypes + HasHostTypes +{ + fn update_client_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event; +} diff --git a/crates/ibc-framework/src/core/traits/handlers/mod.rs b/crates/ibc-framework/src/core/traits/handlers/mod.rs new file mode 100644 index 0000000000..4a9b38e378 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/handlers/mod.rs @@ -0,0 +1 @@ +pub mod update_client; diff --git a/crates/ibc-framework/src/core/traits/handlers/update_client.rs b/crates/ibc-framework/src/core/traits/handlers/update_client.rs new file mode 100644 index 0000000000..76907af452 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/handlers/update_client.rs @@ -0,0 +1,49 @@ +use crate::core::aliases::client::{ClientHeader, ClientState, ConsensusState}; +use crate::core::traits::client::{HasAnyClientTypes, HasClientTypes}; +use crate::core::traits::error::HasError; +use crate::core::traits::ibc::HasIbcTypes; +use crate::core::traits::sync::Async; + +pub trait HasAnyUpdateClientHandler: HasIbcTypes + HasAnyClientTypes + HasError { + type AnyUpdateClientHandler: AnyUpdateClientHandler; + + fn check_client_header_and_update_state( + &self, + client_id: &Self::ClientId, + client_state: &Self::AnyClientState, + new_client_header: &Self::AnyClientHeader, + ) -> Result<(Self::AnyClientState, Self::AnyConsensusState), Self::Error> { + Self::AnyUpdateClientHandler::check_client_header_and_update_state( + self, + client_id, + client_state, + new_client_header, + ) + } +} + +pub trait AnyUpdateClientHandler: Async +where + Context: HasIbcTypes + HasAnyClientTypes + HasError, +{ + fn check_client_header_and_update_state( + context: &Context, + client_id: &Context::ClientId, + client_state: &Context::AnyClientState, + new_client_header: &Context::AnyClientHeader, + ) -> Result<(Context::AnyClientState, Context::AnyConsensusState), Context::Error>; +} + +pub trait UpdateClientHandler: Async +where + Context: HasIbcTypes + HasError, +{ + type Client: HasClientTypes; + + fn check_client_header_and_update_state( + chain: &Context, + client_id: &Context::ClientId, + client_state: &ClientState, + new_client_header: &ClientHeader, + ) -> Result<(ClientState, ConsensusState), Context::Error>; +} diff --git a/crates/ibc-framework/src/core/traits/host.rs b/crates/ibc-framework/src/core/traits/host.rs new file mode 100644 index 0000000000..1e698fa9e4 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/host.rs @@ -0,0 +1,18 @@ +use crate::core::traits::sync::Async; + +pub trait HasHostTypes: Async { + type Height: Async; + + type Timestamp: Ord + Async; + + // Require non-negative duration + type Duration: Ord + Async; +} + +pub trait HasHostMethods: HasHostTypes { + fn host_height(&self) -> Self::Height; + + fn host_timestamp(&self) -> Self::Timestamp; + + fn add_duration(time: &Self::Timestamp, duration: &Self::Duration) -> Self::Timestamp; +} diff --git a/crates/ibc-framework/src/core/traits/ibc.rs b/crates/ibc-framework/src/core/traits/ibc.rs new file mode 100644 index 0000000000..b3301647bf --- /dev/null +++ b/crates/ibc-framework/src/core/traits/ibc.rs @@ -0,0 +1,13 @@ +use crate::core::traits::sync::Async; + +pub trait HasIbcTypes { + type ClientId: Async; + + type ConnectionId: Async; + + type ChannelId: Async; + + type Port: Async; + + type MerkleProof: Async; +} diff --git a/crates/ibc-framework/src/core/traits/message.rs b/crates/ibc-framework/src/core/traits/message.rs new file mode 100644 index 0000000000..d63b1b222c --- /dev/null +++ b/crates/ibc-framework/src/core/traits/message.rs @@ -0,0 +1,13 @@ +use crate::core::traits::sync::Async; + +pub trait HasMessageTypes { + type Message: Async; + + type MessageType: Eq + Async; + + type Signer: Async; +} + +pub trait HasMessageMethods: HasMessageTypes { + fn message_type(message: &Self::Message) -> Self::MessageType; +} diff --git a/crates/ibc-framework/src/core/traits/message_handler.rs b/crates/ibc-framework/src/core/traits/message_handler.rs new file mode 100644 index 0000000000..0c4c98adc4 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/message_handler.rs @@ -0,0 +1,9 @@ +use crate::core::traits::error::HasError; +use crate::core::traits::message::HasMessageTypes; + +pub trait MessageHandler +where + Context: HasMessageTypes + HasError, +{ + fn handle_message(context: &Context, message: &Context::Message) -> Result<(), Context::Error>; +} diff --git a/crates/ibc-framework/src/core/traits/messages/ibc.rs b/crates/ibc-framework/src/core/traits/messages/ibc.rs new file mode 100644 index 0000000000..1d5bb2037a --- /dev/null +++ b/crates/ibc-framework/src/core/traits/messages/ibc.rs @@ -0,0 +1,5 @@ +use crate::core::traits::messages::update_client::HasUpdateClientMessage; + +pub trait HasIbcMessages: HasUpdateClientMessage {} + +impl HasIbcMessages for Context where Context: HasUpdateClientMessage {} diff --git a/crates/ibc-framework/src/core/traits/messages/mod.rs b/crates/ibc-framework/src/core/traits/messages/mod.rs new file mode 100644 index 0000000000..27a26e959c --- /dev/null +++ b/crates/ibc-framework/src/core/traits/messages/mod.rs @@ -0,0 +1,2 @@ +pub mod ibc; +pub mod update_client; diff --git a/crates/ibc-framework/src/core/traits/messages/update_client.rs b/crates/ibc-framework/src/core/traits/messages/update_client.rs new file mode 100644 index 0000000000..3fbdf64a29 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/messages/update_client.rs @@ -0,0 +1,40 @@ +use crate::core::traits::client::HasAnyClientTypes; +use crate::core::traits::error::HasError; +use crate::core::traits::ibc::HasIbcTypes; +use crate::core::traits::message::HasMessageTypes; +use crate::core::traits::sync::Async; + +pub trait HasUpdateClientMessage: HasAnyClientTypes + HasIbcTypes + HasMessageTypes { + const MESSAGE_TYPE: Self::MessageType; + + type UpdateClientMessage: Async; + + fn try_extract_update_client_message( + message: &Self::Message, + ) -> Option<&Self::UpdateClientMessage>; + + fn message_client_id(message: &Self::UpdateClientMessage) -> &Self::ClientId; + + fn message_client_header(message: &Self::UpdateClientMessage) -> &Self::AnyClientHeader; +} + +pub trait UpdateClientMessageHandler: Async +where + Context: HasUpdateClientMessage + HasError, +{ + fn handle_update_client_message( + context: &Context, + message: &Context::UpdateClientMessage, + ) -> Result<(), Context::Error>; +} + +pub trait HasUpdateClientMessageHandler: HasUpdateClientMessage + HasError { + type UpdateClientMessageHandler: UpdateClientMessageHandler; + + fn handle_update_client_message( + &self, + message: &Self::UpdateClientMessage, + ) -> Result<(), Self::Error> { + Self::UpdateClientMessageHandler::handle_update_client_message(self, message) + } +} diff --git a/crates/ibc-framework/src/core/traits/mod.rs b/crates/ibc-framework/src/core/traits/mod.rs new file mode 100644 index 0000000000..9d02097ca3 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/mod.rs @@ -0,0 +1,13 @@ +pub mod client; +pub mod error; +pub mod event; +pub mod events; +pub mod handlers; +pub mod host; +pub mod ibc; +pub mod message; +pub mod message_handler; +pub mod messages; +pub mod prism; +pub mod stores; +pub mod sync; diff --git a/crates/ibc-framework/src/core/traits/prism.rs b/crates/ibc-framework/src/core/traits/prism.rs new file mode 100644 index 0000000000..5360b0a51c --- /dev/null +++ b/crates/ibc-framework/src/core/traits/prism.rs @@ -0,0 +1,9 @@ +use crate::core::traits::sync::Async; + +pub trait Prism: Async { + fn into(subdata: SubData) -> Data; + + fn try_from(data: Data) -> Option; + + fn try_from_ref(data: &Data) -> Option<&SubData>; +} diff --git a/crates/ibc-framework/src/core/traits/stores/client_reader.rs b/crates/ibc-framework/src/core/traits/stores/client_reader.rs new file mode 100644 index 0000000000..f37c0ad3f2 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/stores/client_reader.rs @@ -0,0 +1,172 @@ +use crate::core::traits::client::{ContainsClient, HasAnyClientTypes, HasClientTypes}; +use crate::core::traits::error::HasError; +use crate::core::traits::host::HasHostTypes; +use crate::core::traits::ibc::HasIbcTypes; + +pub trait AnyClientReader +where + Context: HasAnyClientTypes + HasIbcTypes + HasHostTypes + HasError, +{ + fn get_client_type( + context: &Context, + client_id: &Context::ClientId, + ) -> Result; + + fn get_any_client_state( + context: &Context, + client_id: &Context::ClientId, + ) -> Result; + + fn get_latest_any_consensus_state( + context: &Context, + client_id: &Context::ClientId, + ) -> Result; + + fn get_any_consensus_state_at_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error>; + + fn get_any_consensus_state_after_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error>; + + fn get_any_consensus_state_before_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error>; +} + +pub trait HasAnyClientReader: HasAnyClientTypes + HasIbcTypes + HasHostTypes + HasError { + type AnyClientReader: AnyClientReader; + + fn get_client_type(&self, client_id: &Self::ClientId) -> Result { + Self::AnyClientReader::get_client_type(self, client_id) + } + + fn get_any_client_state( + &self, + client_id: &Self::ClientId, + ) -> Result { + Self::AnyClientReader::get_any_client_state(self, client_id) + } + + fn get_latest_any_consensus_state( + &self, + client_id: &Self::ClientId, + ) -> Result { + Self::AnyClientReader::get_latest_any_consensus_state(self, client_id) + } + + fn get_any_consensus_state_at_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error> { + Self::AnyClientReader::get_any_consensus_state_at_height(self, client_id, height) + } + + fn get_any_consensus_state_after_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error> { + Self::AnyClientReader::get_any_consensus_state_after_height(self, client_id, height) + } + + fn get_any_consensus_state_before_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error> { + Self::AnyClientReader::get_any_consensus_state_after_height(self, client_id, height) + } +} + +pub struct MismatchClientFormat { + pub expected_client_type: ClientType, +} + +pub trait ClientReader +where + Context: HasError + HasIbcTypes + HasHostTypes + ContainsClient, + Client: HasClientTypes, +{ + fn get_client_state( + context: &Context, + client_id: &Context::ClientId, + ) -> Result; + + fn get_latest_consensus_state( + context: &Context, + client_id: &Context::ClientId, + ) -> Result; + + fn get_consensus_state_at_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error>; + + fn get_consensus_state_after_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error>; + + fn get_consensus_state_before_height( + context: &Context, + client_id: &Context::ClientId, + height: &Context::Height, + ) -> Result, Context::Error>; +} + +pub trait HasClientReader: + HasError + HasIbcTypes + HasHostTypes + ContainsClient +where + Client: HasClientTypes, +{ + type ClientReader: ClientReader; + + fn get_client_state( + &self, + client_id: &Self::ClientId, + ) -> Result { + Self::ClientReader::get_client_state(self, client_id) + } + + fn get_latest_consensus_state( + &self, + client_id: &Self::ClientId, + ) -> Result { + Self::ClientReader::get_latest_consensus_state(self, client_id) + } + + fn get_consensus_state_at_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error> { + Self::ClientReader::get_consensus_state_at_height(self, client_id, height) + } + + fn get_consensus_state_after_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error> { + Self::ClientReader::get_consensus_state_after_height(self, client_id, height) + } + + fn get_consensus_state_before_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error> { + Self::ClientReader::get_consensus_state_before_height(self, client_id, height) + } +} diff --git a/crates/ibc-framework/src/core/traits/stores/client_writer.rs b/crates/ibc-framework/src/core/traits/stores/client_writer.rs new file mode 100644 index 0000000000..c887260d2a --- /dev/null +++ b/crates/ibc-framework/src/core/traits/stores/client_writer.rs @@ -0,0 +1,40 @@ +use crate::core::traits::client::HasAnyClientTypes; +use crate::core::traits::error::HasError; +use crate::core::traits::ibc::HasIbcTypes; + +pub trait AnyClientWriter +where + Context: HasAnyClientTypes + HasIbcTypes + HasError, +{ + fn set_any_client_state( + context: &Context, + client_id: &Context::ClientId, + client_state: &Context::AnyClientState, + ) -> Result<(), Context::Error>; + + fn set_any_consensus_state( + context: &Context, + client_id: &Context::ClientId, + consensus_state: &Context::AnyConsensusState, + ) -> Result<(), Context::Error>; +} + +pub trait HasAnyClientWriter: HasAnyClientTypes + HasIbcTypes + HasError { + type AnyClientWriter: AnyClientWriter; + + fn set_any_client_state( + &self, + client_id: &Self::ClientId, + client_state: &Self::AnyClientState, + ) -> Result<(), Self::Error> { + Self::AnyClientWriter::set_any_client_state(self, client_id, client_state) + } + + fn set_any_consensus_state( + &self, + client_id: &Self::ClientId, + consensus_state: &Self::AnyConsensusState, + ) -> Result<(), Self::Error> { + Self::AnyClientWriter::set_any_consensus_state(self, client_id, consensus_state) + } +} diff --git a/crates/ibc-framework/src/core/traits/stores/kvstore.rs b/crates/ibc-framework/src/core/traits/stores/kvstore.rs new file mode 100644 index 0000000000..05301ea377 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/stores/kvstore.rs @@ -0,0 +1,20 @@ +use crate::core::traits::error::HasError; +use crate::core::traits::sync::Async; + +pub trait ReadOnlyKvStore: HasError +where + Key: Async, + Value: Async, +{ + fn has(key: &Key) -> Result; + + fn get(key: &Key) -> Result, Self::Error>; +} + +pub trait ReadWriteKvStore: ReadOnlyKvStore +where + Key: Async, + Value: Async, +{ + fn set(key: &Key, value: &Value) -> Result<(), Self::Error>; +} diff --git a/crates/ibc-framework/src/core/traits/stores/mod.rs b/crates/ibc-framework/src/core/traits/stores/mod.rs new file mode 100644 index 0000000000..7b9b44d527 --- /dev/null +++ b/crates/ibc-framework/src/core/traits/stores/mod.rs @@ -0,0 +1,3 @@ +pub mod client_reader; +pub mod client_writer; +pub mod kvstore; diff --git a/crates/ibc-framework/src/core/traits/sync.rs b/crates/ibc-framework/src/core/traits/sync.rs new file mode 100644 index 0000000000..507eb8979f --- /dev/null +++ b/crates/ibc-framework/src/core/traits/sync.rs @@ -0,0 +1,3 @@ +pub trait Async: Sized + Send + Sync + 'static {} + +impl Async for A where A: Sized + Send + Sync + 'static {} diff --git a/crates/ibc-framework/src/lib.rs b/crates/ibc-framework/src/lib.rs new file mode 100644 index 0000000000..2bbb094a51 --- /dev/null +++ b/crates/ibc-framework/src/lib.rs @@ -0,0 +1,11 @@ +#![no_std] +#![allow(clippy::type_complexity)] +#![allow(clippy::too_many_arguments)] + +extern crate alloc; + +mod std_prelude; + +pub mod all_for_one; +pub mod core; +pub mod one_for_all; diff --git a/crates/ibc-framework/src/one_for_all/components/default.rs b/crates/ibc-framework/src/one_for_all/components/default.rs new file mode 100644 index 0000000000..20096398e5 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/components/default.rs @@ -0,0 +1,18 @@ +use crate::core::impls::message_handlers::update_client::BaseUpdateClientMessageHandler; +use crate::one_for_all::impls::stores::{OfaClientReader, OfaClientWriter}; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::traits::components::{OfaChainComponents, OfaClientComponents}; + +pub struct DefaultChainComponents; + +impl OfaChainComponents for DefaultChainComponents +where + Chain: OfaChain, + Chain::ClientComponents: OfaClientComponents, +{ + type AnyClientReader = OfaClientReader; + + type AnyClientWriter = OfaClientWriter; + + type UpdateClientMessageHandler = BaseUpdateClientMessageHandler; +} diff --git a/crates/ibc-framework/src/one_for_all/components/mod.rs b/crates/ibc-framework/src/one_for_all/components/mod.rs new file mode 100644 index 0000000000..1be8d340b8 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/components/mod.rs @@ -0,0 +1 @@ +pub mod default; diff --git a/crates/ibc-framework/src/one_for_all/impls/chain.rs b/crates/ibc-framework/src/one_for_all/impls/chain.rs new file mode 100644 index 0000000000..d94ce76088 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/impls/chain.rs @@ -0,0 +1,162 @@ +use crate::core::traits::client::{HasAnyClientMethods, HasAnyClientTypes}; +use crate::core::traits::error::HasError; +use crate::core::traits::event::{HasEventEmitter, HasEventTypes}; +use crate::core::traits::host::{HasHostMethods, HasHostTypes}; +use crate::core::traits::ibc::HasIbcTypes; +use crate::core::traits::message::{HasMessageMethods, HasMessageTypes}; +use crate::core::traits::messages::update_client::HasUpdateClientMessage; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::types::chain::OfaChainWrapper; + +impl HasError for OfaChainWrapper +where + Chain: OfaChain, +{ + type Error = Chain::Error; +} + +impl HasEventTypes for OfaChainWrapper +where + Chain: OfaChain, +{ + type Event = Chain::Event; +} + +impl HasEventEmitter for OfaChainWrapper +where + Chain: OfaChain, +{ + fn emit_event(&self, event: &Self::Event) { + self.chain.emit_event(event) + } +} + +impl HasHostTypes for OfaChainWrapper +where + Chain: OfaChain, +{ + type Height = Chain::Height; + + type Timestamp = Chain::Timestamp; + + type Duration = Chain::Duration; +} + +impl HasHostMethods for OfaChainWrapper +where + Chain: OfaChain, +{ + fn host_height(&self) -> Self::Height { + self.chain.host_height() + } + + fn host_timestamp(&self) -> Self::Timestamp { + self.chain.host_timestamp() + } + + fn add_duration(time: &Self::Timestamp, duration: &Self::Duration) -> Self::Timestamp { + Chain::add_duration(time, duration) + } +} + +impl HasIbcTypes for OfaChainWrapper +where + Chain: OfaChain, +{ + type ClientId = Chain::ClientId; + + type ConnectionId = Chain::ConnectionId; + + type ChannelId = Chain::ChannelId; + + type Port = Chain::Port; + + type MerkleProof = Chain::MerkleProof; +} + +impl HasMessageTypes for OfaChainWrapper +where + Chain: OfaChain, +{ + type Message = Chain::Message; + + type MessageType = Chain::MessageType; + + type Signer = Chain::Signer; +} + +impl HasMessageMethods for OfaChainWrapper +where + Chain: OfaChain, +{ + fn message_type(message: &Self::Message) -> Self::MessageType { + Chain::message_type(message) + } +} + +impl HasAnyClientTypes for OfaChainWrapper +where + Chain: OfaChain, +{ + type ClientType = Chain::ClientType; + + type AnyClientState = Chain::AnyClientState; + + type AnyConsensusState = Chain::AnyConsensusState; + + type AnyClientHeader = Chain::AnyClientHeader; + + type AnyMisbehavior = Chain::AnyMisbehavior; +} + +impl HasAnyClientMethods for OfaChainWrapper +where + Chain: OfaChain, +{ + fn client_state_type(client_state: &Self::AnyClientState) -> Self::ClientType { + Chain::client_state_type(client_state) + } + + fn client_state_is_frozen(client_state: &Self::AnyClientState) -> bool { + Chain::client_state_is_frozen(client_state) + } + + fn client_state_trusting_period(client_state: &Self::AnyClientState) -> Self::Duration { + Chain::client_state_trusting_period(client_state) + } + + fn client_state_latest_height(client_state: &Self::AnyClientState) -> Self::Height { + Chain::client_state_latest_height(client_state) + } + + fn consensus_state_timestamp(consensus_state: &Self::AnyConsensusState) -> Self::Timestamp { + Chain::consensus_state_timestamp(consensus_state) + } + + fn client_header_height(client_header: &Self::AnyClientHeader) -> Self::Height { + Chain::client_header_height(client_header) + } +} + +impl HasUpdateClientMessage for OfaChainWrapper +where + Chain: OfaChain, +{ + const MESSAGE_TYPE: Self::MessageType = Chain::UPDATE_CLIENT_MESSAGE_TYPE; + + type UpdateClientMessage = Chain::UpdateClientMessage; + + fn try_extract_update_client_message( + message: &Self::Message, + ) -> Option<&Self::UpdateClientMessage> { + Chain::try_extract_update_client_message(message) + } + + fn message_client_id(message: &Self::UpdateClientMessage) -> &Self::ClientId { + Chain::update_client_message_client_id(message) + } + + fn message_client_header(message: &Self::UpdateClientMessage) -> &Self::AnyClientHeader { + Chain::update_client_message_client_header(message) + } +} diff --git a/crates/ibc-framework/src/one_for_all/impls/components.rs b/crates/ibc-framework/src/one_for_all/impls/components.rs new file mode 100644 index 0000000000..881f843cf8 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/impls/components.rs @@ -0,0 +1,41 @@ +use crate::core::traits::handlers::update_client::HasAnyUpdateClientHandler; +use crate::core::traits::messages::update_client::HasUpdateClientMessageHandler; +use crate::core::traits::stores::client_reader::HasAnyClientReader; +use crate::core::traits::stores::client_writer::HasAnyClientWriter; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::traits::components::{OfaChainComponents, OfaClientComponents}; +use crate::one_for_all::types::chain::OfaChainWrapper; + +impl HasAnyClientReader for OfaChainWrapper +where + Chain: OfaChain, + Chain::ChainComponents: OfaChainComponents, +{ + type AnyClientReader = >::AnyClientReader; +} + +impl HasAnyClientWriter for OfaChainWrapper +where + Chain: OfaChain, + Chain::ChainComponents: OfaChainComponents, +{ + type AnyClientWriter = >::AnyClientWriter; +} + +impl HasAnyUpdateClientHandler for OfaChainWrapper +where + Chain: OfaChain, + Chain::ClientComponents: OfaClientComponents, +{ + type AnyUpdateClientHandler = + >::AnyUpdateClientHandler; +} + +impl HasUpdateClientMessageHandler for OfaChainWrapper +where + Chain: OfaChain, + Chain::ChainComponents: OfaChainComponents, +{ + type UpdateClientMessageHandler = + >::UpdateClientMessageHandler; +} diff --git a/crates/ibc-framework/src/one_for_all/impls/error.rs b/crates/ibc-framework/src/one_for_all/impls/error.rs new file mode 100644 index 0000000000..40f6f91141 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/impls/error.rs @@ -0,0 +1,44 @@ +use crate::core::impls::message_handlers::dispatch::InjectDispatchError; +use crate::core::impls::message_handlers::update_client::InjectUpdateClientError; +use crate::core::traits::client::InjectClientTypeMismatchError; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::types::chain::OfaChainWrapper; + +impl InjectClientTypeMismatchError for OfaChainWrapper +where + Chain: OfaChain, +{ + fn client_type_mismatch_error(expected_client_type: &Self::ClientType) -> Self::Error { + Chain::client_type_mismatch_error(expected_client_type) + } +} + +impl InjectDispatchError for OfaChainWrapper +where + Chain: OfaChain, +{ + fn unknown_message_error(message_type: &Self::MessageType) -> Self::Error { + Chain::unknown_message_error(message_type) + } + + fn parse_message_error(message_type: &Self::MessageType) -> Self::Error { + Chain::parse_message_error(message_type) + } +} + +impl InjectUpdateClientError for OfaChainWrapper +where + Chain: OfaChain, +{ + fn client_frozen_error(client_id: &Self::ClientId) -> Self::Error { + Chain::client_frozen_error(client_id) + } + + fn client_expired_error( + client_id: &Self::ClientId, + current_time: &Self::Timestamp, + latest_allowed_update_time: &Self::Timestamp, + ) -> Self::Error { + Chain::client_expired_error(client_id, current_time, latest_allowed_update_time) + } +} diff --git a/crates/ibc-framework/src/one_for_all/impls/event.rs b/crates/ibc-framework/src/one_for_all/impls/event.rs new file mode 100644 index 0000000000..37d828de67 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/impls/event.rs @@ -0,0 +1,32 @@ +use crate::core::traits::events::misbehavior::InjectMisbehaviorEvent; +use crate::core::traits::events::update_client::InjectUpdateClientEvent; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::types::chain::OfaChainWrapper; + +impl InjectUpdateClientEvent for OfaChainWrapper +where + Chain: OfaChain, +{ + fn update_client_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event { + Chain::update_client_event(client_id, client_type, consensus_height, header) + } +} + +impl InjectMisbehaviorEvent for OfaChainWrapper +where + Chain: OfaChain, +{ + fn misbehavior_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event { + Chain::misbehavior_event(client_id, client_type, consensus_height, header) + } +} diff --git a/crates/ibc-framework/src/one_for_all/impls/mod.rs b/crates/ibc-framework/src/one_for_all/impls/mod.rs new file mode 100644 index 0000000000..25c1f2db30 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/impls/mod.rs @@ -0,0 +1,5 @@ +pub mod chain; +pub mod components; +pub mod error; +pub mod event; +pub mod stores; diff --git a/crates/ibc-framework/src/one_for_all/impls/stores.rs b/crates/ibc-framework/src/one_for_all/impls/stores.rs new file mode 100644 index 0000000000..75ca15909c --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/impls/stores.rs @@ -0,0 +1,86 @@ +use crate::core::traits::stores::client_reader::AnyClientReader; +use crate::core::traits::stores::client_writer::AnyClientWriter; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::types::chain::OfaChainWrapper; + +pub struct OfaClientReader; +pub struct OfaClientWriter; + +impl AnyClientReader> for OfaClientReader +where + Chain: OfaChain, +{ + fn get_client_type( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + ) -> Result { + context.chain.get_client_type(client_id) + } + + fn get_any_client_state( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + ) -> Result { + context.chain.get_any_client_state(client_id) + } + + fn get_latest_any_consensus_state( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + ) -> Result { + context.chain.get_latest_any_consensus_state(client_id) + } + + fn get_any_consensus_state_at_height( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + height: &Chain::Height, + ) -> Result, Chain::Error> { + context + .chain + .get_any_consensus_state_at_height(client_id, height) + } + + fn get_any_consensus_state_after_height( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + height: &Chain::Height, + ) -> Result, Chain::Error> { + context + .chain + .get_any_consensus_state_after_height(client_id, height) + } + + fn get_any_consensus_state_before_height( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + height: &Chain::Height, + ) -> Result, Chain::Error> { + context + .chain + .get_any_consensus_state_before_height(client_id, height) + } +} + +impl AnyClientWriter> for OfaClientWriter +where + Chain: OfaChain, +{ + fn set_any_client_state( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + client_state: &Chain::AnyClientState, + ) -> Result<(), Chain::Error> { + context.chain.set_any_client_state(client_id, client_state) + } + + fn set_any_consensus_state( + context: &OfaChainWrapper, + client_id: &Chain::ClientId, + consensus_state: &Chain::AnyConsensusState, + ) -> Result<(), Chain::Error> { + context + .chain + .set_any_consensus_state(client_id, consensus_state) + } +} diff --git a/crates/ibc-framework/src/one_for_all/instances/chain.rs b/crates/ibc-framework/src/one_for_all/instances/chain.rs new file mode 100644 index 0000000000..e0a02b93f1 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/instances/chain.rs @@ -0,0 +1,13 @@ +use crate::all_for_one::traits::base::AfoChainContext; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::traits::components::{OfaChainComponents, OfaClientComponents}; +use crate::one_for_all::types::chain::OfaChainWrapper; + +pub fn ofa_to_afo_chain(chain: Chain) -> impl AfoChainContext +where + Chain: OfaChain, + Chain::ChainComponents: OfaChainComponents, + Chain::ClientComponents: OfaClientComponents, +{ + OfaChainWrapper { chain } +} diff --git a/crates/ibc-framework/src/one_for_all/instances/mod.rs b/crates/ibc-framework/src/one_for_all/instances/mod.rs new file mode 100644 index 0000000000..28ac57df57 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/instances/mod.rs @@ -0,0 +1 @@ +pub mod chain; diff --git a/crates/ibc-framework/src/one_for_all/mod.rs b/crates/ibc-framework/src/one_for_all/mod.rs new file mode 100644 index 0000000000..6b148afb07 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/mod.rs @@ -0,0 +1,5 @@ +pub mod components; +pub mod impls; +pub mod instances; +pub mod traits; +pub mod types; diff --git a/crates/ibc-framework/src/one_for_all/traits/chain.rs b/crates/ibc-framework/src/one_for_all/traits/chain.rs new file mode 100644 index 0000000000..8641a64460 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/traits/chain.rs @@ -0,0 +1,171 @@ +use crate::core::traits::sync::Async; + +pub trait OfaChainTypes: Async { + type Error: Async; + + type Event: Async; + + type Height: Async; + + type Timestamp: Ord + Async; + + type Duration: Ord + Async; + + type Message: Async; + + type MessageType: Eq + Async; + + type Signer: Async; + + type ClientId: Async; + + type ConnectionId: Async; + + type ChannelId: Async; + + type Port: Async; + + type MerkleProof: Async; + + type ClientType: Eq + Async; + + type AnyClientState: Async; + + type AnyConsensusState: Async; + + type AnyClientHeader: Async; + + type AnyMisbehavior: Async; + + type UpdateClientMessage: Async; +} + +pub trait OfaChain: OfaChainTypes { + type ChainComponents; + + type ClientComponents; + + // EventEmitter methods + + fn emit_event(&self, event: &Self::Event); + + // Host methods + + fn host_height(&self) -> Self::Height; + + fn host_timestamp(&self) -> Self::Timestamp; + + fn add_duration(time: &Self::Timestamp, duration: &Self::Duration) -> Self::Timestamp; + + // Message methods + + fn message_type(message: &Self::Message) -> Self::MessageType; + + // AnyClient methods + + fn client_state_type(client_state: &Self::AnyClientState) -> Self::ClientType; + + fn client_state_is_frozen(client_state: &Self::AnyClientState) -> bool; + + fn client_state_trusting_period(client_state: &Self::AnyClientState) -> Self::Duration; + + fn client_state_latest_height(client_state: &Self::AnyClientState) -> Self::Height; + + fn consensus_state_timestamp(consensus_state: &Self::AnyConsensusState) -> Self::Timestamp; + + fn client_header_height(client_header: &Self::AnyClientHeader) -> Self::Height; + + // AnyClientReader methods + + fn get_client_type(&self, client_id: &Self::ClientId) -> Result; + + fn get_any_client_state( + &self, + client_id: &Self::ClientId, + ) -> Result; + + fn get_latest_any_consensus_state( + &self, + client_id: &Self::ClientId, + ) -> Result; + + fn get_any_consensus_state_at_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error>; + + fn get_any_consensus_state_after_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error>; + + fn get_any_consensus_state_before_height( + &self, + client_id: &Self::ClientId, + height: &Self::Height, + ) -> Result, Self::Error>; + + // AnyClientWriter methods + + fn set_any_client_state( + &self, + client_id: &Self::ClientId, + client_state: &Self::AnyClientState, + ) -> Result<(), Self::Error>; + + fn set_any_consensus_state( + &self, + client_id: &Self::ClientId, + consensus_state: &Self::AnyConsensusState, + ) -> Result<(), Self::Error>; + + // Error methods + + fn client_type_mismatch_error(expected_client_type: &Self::ClientType) -> Self::Error; + + fn unknown_message_error(message_type: &Self::MessageType) -> Self::Error; + + fn parse_message_error(message_type: &Self::MessageType) -> Self::Error; + + fn client_frozen_error(client_id: &Self::ClientId) -> Self::Error; + + fn client_expired_error( + client_id: &Self::ClientId, + current_time: &Self::Timestamp, + latest_allowed_update_time: &Self::Timestamp, + ) -> Self::Error; + + // Event methods + + fn update_client_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event; + + fn misbehavior_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event; + + // Message methods + + // UpdateClient message + + const UPDATE_CLIENT_MESSAGE_TYPE: Self::MessageType; + + fn try_extract_update_client_message( + message: &Self::Message, + ) -> Option<&Self::UpdateClientMessage>; + + fn update_client_message_client_id(message: &Self::UpdateClientMessage) -> &Self::ClientId; + + fn update_client_message_client_header( + message: &Self::UpdateClientMessage, + ) -> &Self::AnyClientHeader; +} diff --git a/crates/ibc-framework/src/one_for_all/traits/components.rs b/crates/ibc-framework/src/one_for_all/traits/components.rs new file mode 100644 index 0000000000..758035bf48 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/traits/components.rs @@ -0,0 +1,24 @@ +use crate::core::traits::handlers::update_client::AnyUpdateClientHandler; +use crate::core::traits::messages::update_client::UpdateClientMessageHandler; +use crate::core::traits::stores::client_reader::AnyClientReader; +use crate::core::traits::stores::client_writer::AnyClientWriter; +use crate::one_for_all::traits::chain::OfaChain; +use crate::one_for_all::types::chain::OfaChainWrapper; + +pub trait OfaChainComponents +where + Chain: OfaChain, +{ + type AnyClientReader: AnyClientReader>; + + type AnyClientWriter: AnyClientWriter>; + + type UpdateClientMessageHandler: UpdateClientMessageHandler>; +} + +pub trait OfaClientComponents +where + Chain: OfaChain, +{ + type AnyUpdateClientHandler: AnyUpdateClientHandler>; +} diff --git a/crates/ibc-framework/src/one_for_all/traits/mod.rs b/crates/ibc-framework/src/one_for_all/traits/mod.rs new file mode 100644 index 0000000000..313c8fb078 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/traits/mod.rs @@ -0,0 +1,2 @@ +pub mod chain; +pub mod components; diff --git a/crates/ibc-framework/src/one_for_all/types/chain.rs b/crates/ibc-framework/src/one_for_all/types/chain.rs new file mode 100644 index 0000000000..e8bab6c0d8 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/types/chain.rs @@ -0,0 +1,4 @@ +#[derive(Clone)] +pub struct OfaChainWrapper { + pub chain: Chain, +} diff --git a/crates/ibc-framework/src/one_for_all/types/mod.rs b/crates/ibc-framework/src/one_for_all/types/mod.rs new file mode 100644 index 0000000000..28ac57df57 --- /dev/null +++ b/crates/ibc-framework/src/one_for_all/types/mod.rs @@ -0,0 +1 @@ +pub mod chain; diff --git a/crates/ibc-framework/src/std_prelude.rs b/crates/ibc-framework/src/std_prelude.rs new file mode 100644 index 0000000000..bdce26208e --- /dev/null +++ b/crates/ibc-framework/src/std_prelude.rs @@ -0,0 +1,15 @@ +pub use core::prelude::v1::*; + +// Re-export according to alloc::prelude::v1 because it is not yet stabilized +// https://doc.rust-lang.org/src/alloc/prelude/v1.rs.html +pub use alloc::borrow::ToOwned; +pub use alloc::boxed::Box; +pub use alloc::string::{String, ToString}; +pub use alloc::vec::Vec; + +pub use alloc::format; +pub use alloc::vec; + +// Those are exported by default in the std prelude in Rust 2021 +pub use core::convert::{TryFrom, TryInto}; +pub use core::iter::FromIterator; From 4a7c9ba47e3965a866017bb7de79a00f12a50c34 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 1 Feb 2023 12:22:31 +0100 Subject: [PATCH 2/4] Add draft work for ibc-cosmos --- Cargo.lock | 302 +++++++++++++++++- Cargo.toml | 1 + crates/ibc-cosmos/Cargo.toml | 27 ++ .../src/all_for_one/instances/mod.rs | 1 + .../instances/update_client/mod.rs | 1 + .../instances/update_client/tendermint.rs | 33 ++ crates/ibc-cosmos/src/all_for_one/mod.rs | 2 + .../src/all_for_one/traits/dynamic.rs | 46 +++ .../ibc-cosmos/src/all_for_one/traits/mod.rs | 2 + .../src/all_for_one/traits/tendermint.rs | 46 +++ .../ibc-cosmos/src/clients/dynamic/client.rs | 175 ++++++++++ crates/ibc-cosmos/src/clients/dynamic/mod.rs | 1 + crates/ibc-cosmos/src/clients/mod.rs | 2 + .../src/clients/tendermint/client.rs | 196 ++++++++++++ .../ibc-cosmos/src/clients/tendermint/mod.rs | 2 + .../src/clients/tendermint/update_client.rs | 208 ++++++++++++ crates/ibc-cosmos/src/lib.rs | 4 + .../src/one_for_all/components/mod.rs | 1 + .../ibc-cosmos/src/one_for_all/impls/chain.rs | 237 ++++++++++++++ .../ibc-cosmos/src/one_for_all/impls/mod.rs | 1 + crates/ibc-cosmos/src/one_for_all/mod.rs | 4 + .../src/one_for_all/traits/chain.rs | 85 +++++ .../src/one_for_all/traits/client.rs | 75 +++++ .../ibc-cosmos/src/one_for_all/traits/mod.rs | 2 + .../ibc-cosmos/src/one_for_all/types/chain.rs | 3 + .../ibc-cosmos/src/one_for_all/types/mod.rs | 1 + crates/ibc-cosmos/src/types/event.rs | 31 ++ crates/ibc-cosmos/src/types/message.rs | 35 ++ crates/ibc-cosmos/src/types/mod.rs | 2 + 29 files changed, 1524 insertions(+), 2 deletions(-) create mode 100644 crates/ibc-cosmos/Cargo.toml create mode 100644 crates/ibc-cosmos/src/all_for_one/instances/mod.rs create mode 100644 crates/ibc-cosmos/src/all_for_one/instances/update_client/mod.rs create mode 100644 crates/ibc-cosmos/src/all_for_one/instances/update_client/tendermint.rs create mode 100644 crates/ibc-cosmos/src/all_for_one/mod.rs create mode 100644 crates/ibc-cosmos/src/all_for_one/traits/dynamic.rs create mode 100644 crates/ibc-cosmos/src/all_for_one/traits/mod.rs create mode 100644 crates/ibc-cosmos/src/all_for_one/traits/tendermint.rs create mode 100644 crates/ibc-cosmos/src/clients/dynamic/client.rs create mode 100644 crates/ibc-cosmos/src/clients/dynamic/mod.rs create mode 100644 crates/ibc-cosmos/src/clients/mod.rs create mode 100644 crates/ibc-cosmos/src/clients/tendermint/client.rs create mode 100644 crates/ibc-cosmos/src/clients/tendermint/mod.rs create mode 100644 crates/ibc-cosmos/src/clients/tendermint/update_client.rs create mode 100644 crates/ibc-cosmos/src/lib.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/components/mod.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/impls/chain.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/impls/mod.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/mod.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/traits/chain.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/traits/client.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/traits/mod.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/types/chain.rs create mode 100644 crates/ibc-cosmos/src/one_for_all/types/mod.rs create mode 100644 crates/ibc-cosmos/src/types/event.rs create mode 100644 crates/ibc-cosmos/src/types/message.rs create mode 100644 crates/ibc-cosmos/src/types/mod.rs diff --git a/Cargo.lock b/Cargo.lock index e4b8c19b1d..1045309e30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,6 +62,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.8", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -120,6 +131,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "ascii" version = "1.1.0" @@ -312,6 +329,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -330,6 +359,51 @@ dependencies = [ "generic-array", ] +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "brotli" version = "3.3.4" @@ -384,6 +458,12 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + [[package]] name = "bytecount" version = "0.6.3" @@ -817,7 +897,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if 1.0.0", - "hashbrown", + "hashbrown 0.12.3", "lock_api", "once_cell", "parking_lot_core", @@ -932,6 +1012,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "displaydoc" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dyn-clone" version = "1.0.9" @@ -1161,6 +1252,9 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", "static_assertions", ] @@ -1241,6 +1335,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -1474,6 +1574,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1733,6 +1842,36 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ibc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a730a189bda73e2d2ac215b49fd2c533388b966dd59c9d7550e520f6b9e711" +dependencies = [ + "bytes", + "derive_more", + "displaydoc", + "dyn-clone", + "erased-serde", + "ibc-proto 0.24.1", + "ics23", + "num-traits", + "primitive-types", + "prost", + "safe-regex", + "serde", + "serde_derive", + "serde_json", + "sha2 0.10.6", + "subtle-encoding", + "tendermint", + "tendermint-light-client-verifier", + "tendermint-proto 0.28.0", + "time 0.3.17", + "tracing", + "uint", +] + [[package]] name = "ibc-chain-registry" version = "0.2.0" @@ -1751,6 +1890,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "ibc-cosmos" +version = "0.19.0" +dependencies = [ + "async-trait", + "ibc", + "ibc-framework", + "ibc-proto 0.24.1", + "tendermint", + "tendermint-light-client-verifier", + "tendermint-proto 0.28.0", +] + [[package]] name = "ibc-framework" version = "0.1.0" @@ -1805,9 +1957,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30b46bcc4540116870cfb184f338b45174a7560ad46dd74e4cb4e81e005e2056" dependencies = [ "base64", + "borsh", "bytes", "flex-error", + "parity-scale-codec", "prost", + "scale-info", "serde", "subtle-encoding", "tendermint-proto 0.28.0", @@ -2111,6 +2266,15 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + [[package]] name = "impl-serde" version = "0.4.0" @@ -2120,6 +2284,17 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "indenter" version = "0.3.3" @@ -2133,7 +2308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -2618,6 +2793,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "notify" version = "4.0.17" @@ -2862,6 +3046,32 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "parity-scale-codec" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +dependencies = [ + "proc-macro-crate 1.3.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -3066,10 +3276,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" dependencies = [ "fixed-hash", + "impl-codec", "impl-serde", "uint", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3213,6 +3443,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -3498,6 +3734,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + [[package]] name = "rustc_version" version = "0.4.0" @@ -3662,6 +3904,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "001cf62ece89779fd16105b5f515ad0e5cedcd5440d3dd806bb067978e7c3608" +dependencies = [ + "cfg-if 1.0.0", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "303959cf613a6f6efd19ed4b4ad5bf79966a13352716299ad532cfb115f4205c" +dependencies = [ + "proc-macro-crate 1.3.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "schannel" version = "0.1.20" @@ -4180,6 +4446,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.3.0" @@ -4636,6 +4908,23 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tonic" version = "0.8.3" @@ -5358,6 +5647,15 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zeroize" version = "1.5.7" diff --git a/Cargo.toml b/Cargo.toml index 0e28fc3484..b2412e5ea5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "crates/relayer-runtime", "crates/relayer-cosmos", "crates/ibc-framework", + "crates/ibc-cosmos", "crates/telemetry", "crates/chain-registry", "tools/integration-test", diff --git a/crates/ibc-cosmos/Cargo.toml b/crates/ibc-cosmos/Cargo.toml new file mode 100644 index 0000000000..e88e53b00e --- /dev/null +++ b/crates/ibc-cosmos/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "ibc-cosmos" +version = "0.19.0" +edition = "2021" +license = "Apache-2.0" +readme = "README.md" +keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] +repository = "https://github.com/informalsystems/ibc-rs" +authors = ["Informal Systems "] +rust-version = "1.60" +description = """ + Implementation of an IBC Relayer in Rust, as a library +""" + +[package.metadata.docs.rs] +all-features = true + +[features] + +[dependencies] +async-trait = "0.1.56" +ibc = { version = "0.27.0" } +ibc-proto = { version = "0.24.0" } +ibc-framework = { version = "0.1.0", path = "../ibc-framework" } +tendermint = { version = "=0.28.0", default-features = false } +tendermint-proto = { version = "=0.28.0", default-features = false } +tendermint-light-client-verifier = { version = "=0.28.0", default-features = false } diff --git a/crates/ibc-cosmos/src/all_for_one/instances/mod.rs b/crates/ibc-cosmos/src/all_for_one/instances/mod.rs new file mode 100644 index 0000000000..4a9b38e378 --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/instances/mod.rs @@ -0,0 +1 @@ +pub mod update_client; diff --git a/crates/ibc-cosmos/src/all_for_one/instances/update_client/mod.rs b/crates/ibc-cosmos/src/all_for_one/instances/update_client/mod.rs new file mode 100644 index 0000000000..5efd1e3f2c --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/instances/update_client/mod.rs @@ -0,0 +1 @@ +pub mod tendermint; diff --git a/crates/ibc-cosmos/src/all_for_one/instances/update_client/tendermint.rs b/crates/ibc-cosmos/src/all_for_one/instances/update_client/tendermint.rs new file mode 100644 index 0000000000..aaaf594214 --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/instances/update_client/tendermint.rs @@ -0,0 +1,33 @@ +use core::marker::PhantomData; +use ibc_framework::core::impls::handlers::update_client::lift::LiftClientUpdateHandler; +use ibc_framework::core::traits::handlers::update_client::{ + AnyUpdateClientHandler, UpdateClientHandler, +}; + +use crate::all_for_one::traits::dynamic::AfoDynamicChainContext; +use crate::all_for_one::traits::tendermint::AfoTendermintOnlyChainContext; +use crate::clients::tendermint::client::TendermintClient; + +pub fn can_build_tendermint_update_handler( +) -> PhantomData> +where + Context: AfoTendermintOnlyChainContext, +{ + PhantomData:: +} + +pub fn can_build_tendermint_any_update_handler( +) -> PhantomData> +where + Context: AfoTendermintOnlyChainContext, +{ + PhantomData::> +} + +pub fn can_build_dynamic_tendermint_any_update_handler( +) -> PhantomData> +where + Context: AfoDynamicChainContext, +{ + PhantomData::> +} diff --git a/crates/ibc-cosmos/src/all_for_one/mod.rs b/crates/ibc-cosmos/src/all_for_one/mod.rs new file mode 100644 index 0000000000..850a32dc03 --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/mod.rs @@ -0,0 +1,2 @@ +pub mod instances; +pub mod traits; diff --git a/crates/ibc-cosmos/src/all_for_one/traits/dynamic.rs b/crates/ibc-cosmos/src/all_for_one/traits/dynamic.rs new file mode 100644 index 0000000000..f09bdd65d7 --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/traits/dynamic.rs @@ -0,0 +1,46 @@ +use ibc::core::ics23_commitment::merkle::MerkleProof; +use ibc::core::ics24_host::identifier::ClientId; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::all_for_one::traits::base::AfoChainContext; +use ibc_framework::core::traits::error::InjectError; +use ibc_framework::core::traits::stores::client_reader::HasClientReader; +use ibc_proto::google::protobuf::Any; + +use crate::clients::dynamic::client::{ + DynClientHeader, DynClientState, DynConsensusState, DynMisbehavior, +}; +use crate::clients::tendermint::client::TendermintClient; +use crate::clients::tendermint::update_client::Error as UpdateTendermintClientError; + +pub trait AfoDynamicChainContext: + AfoChainContext< + Height = Height, + Timestamp = Timestamp, + Message = Any, + ClientId = ClientId, + MerkleProof = MerkleProof, + AnyClientState = DynClientState, + AnyConsensusState = DynConsensusState, + AnyClientHeader = DynClientHeader, + AnyMisbehavior = DynMisbehavior, + > + InjectError + + HasClientReader +{ +} + +impl AfoDynamicChainContext for Context where + Context: AfoChainContext< + Height = Height, + Timestamp = Timestamp, + Message = Any, + ClientId = ClientId, + MerkleProof = MerkleProof, + AnyClientState = DynClientState, + AnyConsensusState = DynConsensusState, + AnyClientHeader = DynClientHeader, + AnyMisbehavior = DynMisbehavior, + > + InjectError + + HasClientReader +{ +} diff --git a/crates/ibc-cosmos/src/all_for_one/traits/mod.rs b/crates/ibc-cosmos/src/all_for_one/traits/mod.rs new file mode 100644 index 0000000000..dd4cd3a406 --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/traits/mod.rs @@ -0,0 +1,2 @@ +pub mod dynamic; +pub mod tendermint; diff --git a/crates/ibc-cosmos/src/all_for_one/traits/tendermint.rs b/crates/ibc-cosmos/src/all_for_one/traits/tendermint.rs new file mode 100644 index 0000000000..98f889a569 --- /dev/null +++ b/crates/ibc-cosmos/src/all_for_one/traits/tendermint.rs @@ -0,0 +1,46 @@ +use ibc::core::ics23_commitment::merkle::MerkleProof; +use ibc::core::ics24_host::identifier::ClientId; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::all_for_one::traits::base::AfoChainContext; +use ibc_framework::core::traits::error::InjectError; +use ibc_framework::core::traits::stores::client_reader::HasClientReader; +use ibc_proto::google::protobuf::Any; + +use crate::clients::tendermint::client::{ + TendermintClient, TendermintClientHeader, TendermintClientState, TendermintConsensusState, + TendermintMisbehavior, +}; +use crate::clients::tendermint::update_client::Error as UpdateTendermintClientError; + +pub trait AfoTendermintOnlyChainContext: + AfoChainContext< + Height = Height, + Timestamp = Timestamp, + Message = Any, + ClientId = ClientId, + MerkleProof = MerkleProof, + AnyClientState = TendermintClientState, + AnyConsensusState = TendermintConsensusState, + AnyClientHeader = TendermintClientHeader, + AnyMisbehavior = TendermintMisbehavior, + > + InjectError + + HasClientReader +{ +} + +impl AfoTendermintOnlyChainContext for Context where + Context: AfoChainContext< + Height = Height, + Timestamp = Timestamp, + Message = Any, + ClientId = ClientId, + MerkleProof = MerkleProof, + AnyClientState = TendermintClientState, + AnyConsensusState = TendermintConsensusState, + AnyClientHeader = TendermintClientHeader, + AnyMisbehavior = TendermintMisbehavior, + > + InjectError + + HasClientReader +{ +} diff --git a/crates/ibc-cosmos/src/clients/dynamic/client.rs b/crates/ibc-cosmos/src/clients/dynamic/client.rs new file mode 100644 index 0000000000..50abf6fa79 --- /dev/null +++ b/crates/ibc-cosmos/src/clients/dynamic/client.rs @@ -0,0 +1,175 @@ +use core::time::Duration; +use ibc::clients::ics07_tendermint::client_state::ClientState as TendermintClientState; +use ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TendermintConsensusState; +use ibc::clients::ics07_tendermint::header::Header as TendermintClientHeader; +use ibc::clients::ics07_tendermint::misbehaviour::Misbehaviour as TendermintMisbehavior; +use ibc::core::ics02_client::client_state::ClientState; +use ibc::core::ics02_client::client_type::ClientType; +use ibc::core::ics02_client::consensus_state::ConsensusState; +use ibc::core::ics02_client::header::Header as ClientHeader; +use ibc::core::ics02_client::misbehaviour::Misbehaviour; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::core::traits::client::{ + HasAnyClientMethods, HasAnyClientTypes, HasClientTypeFor, +}; +use ibc_framework::core::traits::host::HasHostTypes; +use ibc_framework::core::traits::prism::Prism; + +use crate::clients::tendermint::client::TendermintClient; + +pub struct DynamicClient; + +pub struct DynClientState { + pub client_state: Box, +} + +pub struct DynConsensusState { + pub consensus_state: Box, +} + +pub struct DynClientHeader { + pub client_header: Box, +} + +pub struct DynMisbehavior { + pub misbehavior: Box, +} + +impl HasAnyClientTypes for DynamicClient { + type ClientType = ClientType; + + type AnyClientState = DynClientState; + + type AnyConsensusState = DynConsensusState; + + type AnyClientHeader = DynClientHeader; + + type AnyMisbehavior = DynMisbehavior; +} + +impl Prism for DynamicClient { + fn into(client_state: TendermintClientState) -> DynClientState { + DynClientState::new(client_state) + } + + fn try_from(client_state: DynClientState) -> Option { + Self::try_from_ref(&client_state).cloned() + } + + fn try_from_ref(client_state: &DynClientState) -> Option<&TendermintClientState> { + client_state.client_state.as_any().downcast_ref() + } +} + +impl Prism for DynamicClient { + fn into(consensus_state: TendermintConsensusState) -> DynConsensusState { + DynConsensusState::new(consensus_state) + } + + fn try_from(consensus_state: DynConsensusState) -> Option { + Self::try_from_ref(&consensus_state).cloned() + } + + fn try_from_ref(consensus_state: &DynConsensusState) -> Option<&TendermintConsensusState> { + consensus_state.consensus_state.as_any().downcast_ref() + } +} + +impl Prism for DynamicClient { + fn into(client_header: TendermintClientHeader) -> DynClientHeader { + DynClientHeader::new(client_header) + } + + fn try_from(client_header: DynClientHeader) -> Option { + Self::try_from_ref(&client_header).cloned() + } + + fn try_from_ref(client_header: &DynClientHeader) -> Option<&TendermintClientHeader> { + client_header.client_header.as_any().downcast_ref() + } +} + +impl Prism for DynamicClient { + fn into(misbehavior: TendermintMisbehavior) -> DynMisbehavior { + DynMisbehavior::new(misbehavior) + } + + fn try_from(misbehavior: DynMisbehavior) -> Option { + Self::try_from_ref(&misbehavior).cloned() + } + + fn try_from_ref(misbehavior: &DynMisbehavior) -> Option<&TendermintMisbehavior> { + misbehavior.misbehavior.as_any().downcast_ref() + } +} + +impl HasClientTypeFor for DynamicClient { + const CLIENT_TYPE: ClientType = ClientType::Tendermint; +} + +impl HasHostTypes for DynamicClient { + type Height = Height; + + type Timestamp = Timestamp; + + type Duration = Duration; +} + +impl HasAnyClientMethods for DynamicClient { + fn client_state_type(client_state: &DynClientState) -> Self::ClientType { + client_state.client_state.client_type() + } + + fn client_state_is_frozen(client_state: &DynClientState) -> bool { + client_state.client_state.is_frozen() + } + + fn client_state_trusting_period(client_state: &DynClientState) -> Self::Duration { + client_state.client_state.trusting_period() + } + + fn client_state_latest_height(client_state: &DynClientState) -> Self::Height { + client_state.client_state.latest_height() + } + + fn consensus_state_timestamp(consensus_state: &DynConsensusState) -> Self::Timestamp { + consensus_state.consensus_state.timestamp() + } + + fn client_header_height(client_header: &DynClientHeader) -> Self::Height { + client_header.client_header.height() + } +} + +impl DynClientState { + fn new(client_state: impl ClientState) -> Self { + Self { + client_state: Box::new(client_state), + } + } +} + +impl DynConsensusState { + fn new(consensus_state: impl ConsensusState) -> Self { + Self { + consensus_state: Box::new(consensus_state), + } + } +} + +impl DynClientHeader { + fn new(client_header: impl ClientHeader) -> Self { + Self { + client_header: Box::new(client_header), + } + } +} + +impl DynMisbehavior { + fn new(misbehavior: impl Misbehaviour) -> Self { + Self { + misbehavior: Box::new(misbehavior), + } + } +} diff --git a/crates/ibc-cosmos/src/clients/dynamic/mod.rs b/crates/ibc-cosmos/src/clients/dynamic/mod.rs new file mode 100644 index 0000000000..b9babe5bc1 --- /dev/null +++ b/crates/ibc-cosmos/src/clients/dynamic/mod.rs @@ -0,0 +1 @@ +pub mod client; diff --git a/crates/ibc-cosmos/src/clients/mod.rs b/crates/ibc-cosmos/src/clients/mod.rs new file mode 100644 index 0000000000..dd4cd3a406 --- /dev/null +++ b/crates/ibc-cosmos/src/clients/mod.rs @@ -0,0 +1,2 @@ +pub mod dynamic; +pub mod tendermint; diff --git a/crates/ibc-cosmos/src/clients/tendermint/client.rs b/crates/ibc-cosmos/src/clients/tendermint/client.rs new file mode 100644 index 0000000000..d9a69af4f4 --- /dev/null +++ b/crates/ibc-cosmos/src/clients/tendermint/client.rs @@ -0,0 +1,196 @@ +use core::time::Duration; +use ibc::core::ics02_client::client_state::ClientState; +use ibc::core::ics02_client::client_type::ClientType; +use ibc::core::ics02_client::consensus_state::ConsensusState; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::core::traits::client::{ + HasAnyClientMethods, HasAnyClientTypes, HasClientTypeFor, HasClientTypes, +}; +use ibc_framework::core::traits::host::HasHostTypes; +use ibc_framework::core::traits::prism::Prism; + +pub use ibc::clients::ics07_tendermint::client_state::ClientState as TendermintClientState; +pub use ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TendermintConsensusState; +pub use ibc::clients::ics07_tendermint::header::Header as TendermintClientHeader; +pub use ibc::clients::ics07_tendermint::misbehaviour::Misbehaviour as TendermintMisbehavior; + +use crate::one_for_all::traits::client::OfaCosmosClient; + +pub struct TendermintClient; + +impl OfaCosmosClient for TendermintClient { + type AnyClientState = TendermintClientState; + + type AnyConsensusState = TendermintConsensusState; + + type AnyClientHeader = TendermintClientHeader; + + type AnyMisbehavior = TendermintMisbehavior; + + fn client_state_type(client_state: &TendermintClientState) -> ClientType { + client_state.client_type() + } + + fn client_state_is_frozen(client_state: &TendermintClientState) -> bool { + client_state.is_frozen() + } + + fn client_state_trusting_period(client_state: &TendermintClientState) -> Duration { + client_state.trusting_period + } + + fn client_state_latest_height(client_state: &TendermintClientState) -> Height { + client_state.latest_height() + } + + fn consensus_state_timestamp(consensus_state: &TendermintConsensusState) -> Timestamp { + consensus_state.timestamp() + } + + fn client_header_height(client_header: &TendermintClientHeader) -> Height { + client_header.height() + } + + fn try_into_tendermint_client_state( + client_state: Self::AnyClientState, + ) -> Option { + Some(client_state) + } + + fn try_into_tendermint_client_state_ref( + client_state: &Self::AnyClientState, + ) -> Option<&TendermintClientState> { + Some(client_state) + } + + fn from_tendermint_client_state(client_state: TendermintClientState) -> Self::AnyClientState { + client_state + } + + fn try_into_tendermint_consensus_state( + consensus_state: Self::AnyConsensusState, + ) -> Option { + Some(consensus_state) + } + + fn try_into_tendermint_consensus_state_ref( + consensus_state: &Self::AnyConsensusState, + ) -> Option<&TendermintConsensusState> { + Some(consensus_state) + } + + fn from_tendermint_consensus_state( + consensus_state: TendermintConsensusState, + ) -> Self::AnyConsensusState { + consensus_state + } + + fn try_into_tendermint_client_header( + client_header: Self::AnyClientHeader, + ) -> Option { + Some(client_header) + } + + fn try_into_tendermint_client_header_ref( + client_header: &Self::AnyClientHeader, + ) -> Option<&TendermintClientHeader> { + Some(client_header) + } + + fn from_tendermint_client_header( + client_header: TendermintClientHeader, + ) -> Self::AnyClientHeader { + client_header + } + + fn try_into_tendermint_misbehavior( + misbehavior: Self::AnyMisbehavior, + ) -> Option { + Some(misbehavior) + } + + fn try_into_tendermint_misbehavior_ref( + misbehavior: &Self::AnyMisbehavior, + ) -> Option<&TendermintMisbehavior> { + Some(misbehavior) + } + + fn from_tendermint_misbehavior(misbehavior: TendermintMisbehavior) -> Self::AnyMisbehavior { + misbehavior + } +} + +impl HasClientTypes for TendermintClient { + type ClientState = TendermintClientState; + + type ConsensusState = TendermintConsensusState; + + type ClientHeader = TendermintClientHeader; + + type Misbehavior = TendermintMisbehavior; +} + +impl HasAnyClientTypes for TendermintClient { + type ClientType = ClientType; + + type AnyClientState = TendermintClientState; + + type AnyConsensusState = TendermintConsensusState; + + type AnyClientHeader = TendermintClientHeader; + + type AnyMisbehavior = TendermintMisbehavior; +} + +impl Prism for TendermintClient { + fn into(subdata: T) -> T { + subdata + } + + fn try_from(data: T) -> Option { + Some(data) + } + + fn try_from_ref(data: &T) -> Option<&T> { + Some(data) + } +} + +impl HasClientTypeFor for TendermintClient { + const CLIENT_TYPE: ClientType = ClientType::Tendermint; +} + +impl HasHostTypes for TendermintClient { + type Height = Height; + + type Timestamp = Timestamp; + + type Duration = Duration; +} + +impl HasAnyClientMethods for TendermintClient { + fn client_state_type(client_state: &TendermintClientState) -> Self::ClientType { + client_state.client_type() + } + + fn client_state_is_frozen(client_state: &TendermintClientState) -> bool { + client_state.is_frozen() + } + + fn client_state_trusting_period(client_state: &TendermintClientState) -> Self::Duration { + client_state.trusting_period + } + + fn client_state_latest_height(client_state: &TendermintClientState) -> Self::Height { + client_state.latest_height() + } + + fn consensus_state_timestamp(consensus_state: &TendermintConsensusState) -> Self::Timestamp { + consensus_state.timestamp() + } + + fn client_header_height(client_header: &TendermintClientHeader) -> Self::Height { + client_header.height() + } +} diff --git a/crates/ibc-cosmos/src/clients/tendermint/mod.rs b/crates/ibc-cosmos/src/clients/tendermint/mod.rs new file mode 100644 index 0000000000..0643b8bd42 --- /dev/null +++ b/crates/ibc-cosmos/src/clients/tendermint/mod.rs @@ -0,0 +1,2 @@ +pub mod client; +pub mod update_client; diff --git a/crates/ibc-cosmos/src/clients/tendermint/update_client.rs b/crates/ibc-cosmos/src/clients/tendermint/update_client.rs new file mode 100644 index 0000000000..779685c284 --- /dev/null +++ b/crates/ibc-cosmos/src/clients/tendermint/update_client.rs @@ -0,0 +1,208 @@ +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::core::traits::client::ContainsClient; +use ibc_framework::core::traits::error::{HasError, InjectError}; +use ibc_framework::core::traits::handlers::update_client::UpdateClientHandler; +use ibc_framework::core::traits::host::HasHostMethods; +use ibc_framework::core::traits::ibc::HasIbcTypes; +use ibc_framework::core::traits::stores::client_reader::HasClientReader; +use tendermint::block::Height as BlockHeight; +use tendermint_light_client_verifier::errors::VerificationErrorDetail; +use tendermint_light_client_verifier::operations::voting_power::VotingPowerTally; +use tendermint_light_client_verifier::types::{TrustedBlockState, UntrustedBlockState}; +use tendermint_light_client_verifier::{Verdict, Verifier}; + +use crate::clients::tendermint::client::{ + TendermintClient, TendermintClientHeader, TendermintClientState, TendermintConsensusState, +}; + +pub enum Error { + MismatchRevision { + current_revision: u64, + update_revision: u64, + }, + ConsensusStateNotFound { + height: Height, + }, + RevisionHeightOverflow { + height: u64, + }, + NotEnoughTrust { + tally: VotingPowerTally, + }, + VerificationError { + detail: VerificationErrorDetail, + }, + HeaderTimestampTooHigh { + actual: Timestamp, + max: Timestamp, + }, + HeaderTimestampTooLow { + actual: Timestamp, + max: Timestamp, + }, + InvalidHeight, +} + +impl UpdateClientHandler for TendermintClient +where + Context: HasError, + Context: HasIbcTypes, + Context: HasHostMethods, + Context: HasClientReader, + Context: ContainsClient, + Context: InjectError, +{ + type Client = TendermintClient; + + fn check_client_header_and_update_state( + context: &Context, + client_id: &Context::ClientId, + client_state: &TendermintClientState, + new_client_header: &TendermintClientHeader, + ) -> Result<(TendermintClientState, TendermintConsensusState), Context::Error> { + let new_height = new_client_header.height(); + + let current_revision = client_state.chain_id.version(); + let update_revision = new_client_header.height().revision_number(); + + if current_revision != update_revision { + return Err(Context::inject_error(Error::MismatchRevision { + current_revision, + update_revision, + })); + } + + let new_consensus_state = TendermintConsensusState::from(new_client_header.clone()); + + let m_current_client_consensus_state = + context.get_consensus_state_at_height(client_id, &new_height)?; + + if m_current_client_consensus_state.as_ref() == Some(&new_consensus_state) { + return Ok((client_state.clone(), new_consensus_state)); + } + + { + let trusted_height = new_client_header.trusted_height; + + let trusted_consensus_state = context + .get_consensus_state_at_height(client_id, &trusted_height)? + .ok_or_else(|| { + Context::inject_error(Error::ConsensusStateNotFound { + height: trusted_height, + }) + })?; + + let trusted_revision_height = trusted_height.revision_height(); + + let trusted_block_height = + BlockHeight::try_from(trusted_revision_height).map_err(|_| { + Context::inject_error(Error::RevisionHeightOverflow { + height: trusted_revision_height, + }) + })?; + + let trusted_state = TrustedBlockState { + header_time: trusted_consensus_state.timestamp, + height: trusted_block_height, + next_validators: &new_client_header.trusted_validator_set, + next_validators_hash: trusted_consensus_state.next_validators_hash, + }; + + let untrusted_state = UntrustedBlockState { + signed_header: &new_client_header.signed_header, + validators: &new_client_header.validator_set, + // NB: This will skip the + // VerificationPredicates::next_validators_match check for the + // untrusted state. + next_validators: None, + }; + + let options = client_state.as_light_client_options().unwrap(); + + let now = context.host_timestamp().into_tm_time().unwrap(); + + let verdict = + client_state + .verifier + .verify(untrusted_state, trusted_state, &options, now); + + match verdict { + Verdict::Success => {} + Verdict::NotEnoughTrust(voting_power_tally) => { + return Err(Context::inject_error(Error::NotEnoughTrust { + tally: voting_power_tally, + })); + } + Verdict::Invalid(detail) => { + return Err(Context::inject_error(Error::VerificationError { detail })) + } + } + } + + // If the header has verified, but its corresponding consensus state + // differs from the existing consensus state for that height, freeze the + // client and return the installed consensus state. + // + // Note that this must be done *after* the light client verification. + // So that invalid headers will result in verification errors instead + // of errorneously freezing clients. + if let Some(cs) = m_current_client_consensus_state { + if cs != new_consensus_state { + return Ok(( + client_state + .clone() + .with_frozen_height(new_client_header.height()), + cs, + )); + } + } + + // Monotonicity checks for timestamps for in-the-middle updates + // (cs-new, cs-next, cs-latest) + if new_client_header.height() < client_state.latest_height() { + let m_next_consensus_state = + context.get_consensus_state_after_height(client_id, &new_height)?; + + if let Some(next_cs) = m_next_consensus_state { + // New (untrusted) header timestamp cannot occur after next + // consensus state's height + if new_client_header.signed_header.header().time > next_cs.timestamp { + return Err(Context::inject_error(Error::HeaderTimestampTooHigh { + actual: new_client_header.signed_header.header().time.into(), + max: next_cs.timestamp.into(), + })); + } + } + } + + // (cs-trusted, cs-prev, cs-new) + if new_client_header.trusted_height < new_client_header.height() { + let m_prev_consensus_state = + context.get_consensus_state_after_height(client_id, &new_height)?; + + if let Some(prev_cs) = m_prev_consensus_state { + // New (untrusted) header timestamp cannot occur before the + // previous consensus state's height + if new_client_header.signed_header.header().time < prev_cs.timestamp { + return Err(Context::inject_error(Error::HeaderTimestampTooLow { + actual: new_client_header.signed_header.header().time.into(), + max: prev_cs.timestamp.into(), + })); + } + } + } + + let latest_height = Height::new( + client_state.latest_height.revision_number(), + new_client_header.signed_header.header.height.into(), + ) + .map_err(|_| Context::inject_error(Error::InvalidHeight))?; + + let mut new_client_state = client_state.clone(); + + new_client_state.latest_height = latest_height; + + Ok((new_client_state, new_consensus_state)) + } +} diff --git a/crates/ibc-cosmos/src/lib.rs b/crates/ibc-cosmos/src/lib.rs new file mode 100644 index 0000000000..1f3b8747d2 --- /dev/null +++ b/crates/ibc-cosmos/src/lib.rs @@ -0,0 +1,4 @@ +pub mod all_for_one; +pub mod clients; +pub mod one_for_all; +pub mod types; diff --git a/crates/ibc-cosmos/src/one_for_all/components/mod.rs b/crates/ibc-cosmos/src/one_for_all/components/mod.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/components/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/ibc-cosmos/src/one_for_all/impls/chain.rs b/crates/ibc-cosmos/src/one_for_all/impls/chain.rs new file mode 100644 index 0000000000..5825240880 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/impls/chain.rs @@ -0,0 +1,237 @@ +use core::time::Duration; +use ibc::core::ics02_client::client_type::ClientType; +use ibc::core::ics23_commitment::merkle::MerkleProof; +use ibc::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; +use ibc::signer::Signer; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::core::traits::client::HasAnyClientMethods; +use ibc_framework::core::traits::client::HasAnyClientTypes; +use ibc_framework::one_for_all::components::default::DefaultChainComponents; +use ibc_framework::one_for_all::traits::chain::{OfaChain, OfaChainTypes}; + +use crate::one_for_all::traits::chain::OfaCosmosChain; +use crate::one_for_all::types::chain::OfaCosmosChainWrapper; +use crate::types::event::IbcEvent; +use crate::types::message::{IbcMessage, IbcMessageType, UpdateClientMessage}; + +impl OfaChainTypes for OfaCosmosChainWrapper +where + Chain: OfaCosmosChain, +{ + type Error = Chain::Error; + + type Event = IbcEvent; + + type Height = Height; + + type Timestamp = Timestamp; + + type Duration = Duration; + + type Message = IbcMessage; + + type MessageType = IbcMessageType; + + type Signer = Signer; + + type ClientId = ClientId; + + type ConnectionId = ConnectionId; + + type ChannelId = ChannelId; + + type Port = PortId; + + type MerkleProof = MerkleProof; + + type ClientType = ClientType; + + type AnyClientState = ::AnyClientState; + + type AnyConsensusState = ::AnyConsensusState; + + type AnyClientHeader = ::AnyClientHeader; + + type AnyMisbehavior = ::AnyMisbehavior; + + type UpdateClientMessage = UpdateClientMessage; +} + +#[allow(unused_variables)] +impl OfaChain for OfaCosmosChainWrapper +where + Chain: OfaCosmosChain, +{ + type ChainComponents = DefaultChainComponents; + + type ClientComponents = Chain::AnyClient; + + fn emit_event(&self, event: &Self::Event) { + self.chain.emit_event(event) + } + + fn host_height(&self) -> Height { + self.chain.host_height() + } + + fn host_timestamp(&self) -> Timestamp { + self.chain.host_timestamp() + } + + fn add_duration(time: &Timestamp, duration: &Duration) -> Timestamp { + (*time + *duration).unwrap() + } + + fn message_type(message: &Self::Message) -> IbcMessageType { + message.message_type() + } + + fn client_state_type(client_state: &Self::AnyClientState) -> Self::ClientType { + Chain::AnyClient::client_state_type(client_state) + } + + fn client_state_is_frozen(client_state: &Self::AnyClientState) -> bool { + Chain::AnyClient::client_state_is_frozen(client_state) + } + + fn client_state_trusting_period(client_state: &Self::AnyClientState) -> Duration { + Chain::AnyClient::client_state_trusting_period(client_state) + } + + fn client_state_latest_height(client_state: &Self::AnyClientState) -> Height { + Chain::AnyClient::client_state_latest_height(client_state) + } + + fn consensus_state_timestamp(consensus_state: &Self::AnyConsensusState) -> Timestamp { + Chain::AnyClient::consensus_state_timestamp(consensus_state) + } + + fn client_header_height(client_header: &Self::AnyClientHeader) -> Height { + Chain::AnyClient::client_header_height(client_header) + } + + fn get_client_type(&self, client_id: &ClientId) -> Result { + self.chain.get_client_type(client_id) + } + + fn get_any_client_state( + &self, + client_id: &ClientId, + ) -> Result { + self.chain.get_any_client_state(client_id) + } + + fn get_latest_any_consensus_state( + &self, + client_id: &ClientId, + ) -> Result { + self.chain.get_latest_any_consensus_state(client_id) + } + + fn get_any_consensus_state_at_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, Self::Error> { + self.chain + .get_any_consensus_state_at_height(client_id, height) + } + + fn get_any_consensus_state_after_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, Self::Error> { + self.chain + .get_any_consensus_state_after_height(client_id, height) + } + + fn get_any_consensus_state_before_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, Self::Error> { + self.chain + .get_any_consensus_state_before_height(client_id, height) + } + + fn set_any_client_state( + &self, + client_id: &ClientId, + client_state: &Self::AnyClientState, + ) -> Result<(), Self::Error> { + self.chain.set_any_client_state(client_id, client_state) + } + + fn set_any_consensus_state( + &self, + client_id: &ClientId, + consensus_state: &Self::AnyConsensusState, + ) -> Result<(), Self::Error> { + self.chain + .set_any_consensus_state(client_id, consensus_state) + } + + fn client_type_mismatch_error(expected_client_type: &ClientType) -> Self::Error { + Chain::client_type_mismatch_error(expected_client_type) + } + + fn unknown_message_error(message_type: &IbcMessageType) -> Self::Error { + Chain::unknown_message_error(message_type) + } + + fn parse_message_error(message_type: &IbcMessageType) -> Self::Error { + Chain::parse_message_error(message_type) + } + + fn client_frozen_error(client_id: &ClientId) -> Self::Error { + Chain::client_frozen_error(client_id) + } + + fn client_expired_error( + client_id: &ClientId, + current_time: &Timestamp, + latest_allowed_update_time: &Timestamp, + ) -> Self::Error { + Chain::client_expired_error(client_id, current_time, latest_allowed_update_time) + } + + fn update_client_event( + client_id: &ClientId, + client_type: &ClientType, + consensus_height: &Height, + header: &Self::AnyClientHeader, + ) -> Self::Event { + todo!() + } + + fn misbehavior_event( + client_id: &Self::ClientId, + client_type: &Self::ClientType, + consensus_height: &Self::Height, + header: &Self::AnyClientHeader, + ) -> Self::Event { + todo!() + } + + const UPDATE_CLIENT_MESSAGE_TYPE: IbcMessageType = IbcMessageType::UpdateClient; + + fn try_extract_update_client_message( + message: &IbcMessage, + ) -> Option<&Self::UpdateClientMessage> { + match message { + IbcMessage::UpdateClient(message) => Some(message), + } + } + + fn update_client_message_client_id(message: &Self::UpdateClientMessage) -> &ClientId { + &message.client_id + } + + fn update_client_message_client_header( + message: &Self::UpdateClientMessage, + ) -> &Self::AnyClientHeader { + &message.client_header + } +} diff --git a/crates/ibc-cosmos/src/one_for_all/impls/mod.rs b/crates/ibc-cosmos/src/one_for_all/impls/mod.rs new file mode 100644 index 0000000000..28ac57df57 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/impls/mod.rs @@ -0,0 +1 @@ +pub mod chain; diff --git a/crates/ibc-cosmos/src/one_for_all/mod.rs b/crates/ibc-cosmos/src/one_for_all/mod.rs new file mode 100644 index 0000000000..3c8cbfdc51 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/mod.rs @@ -0,0 +1,4 @@ +pub mod components; +pub mod impls; +pub mod traits; +pub mod types; diff --git a/crates/ibc-cosmos/src/one_for_all/traits/chain.rs b/crates/ibc-cosmos/src/one_for_all/traits/chain.rs new file mode 100644 index 0000000000..6a61c5b76e --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/traits/chain.rs @@ -0,0 +1,85 @@ +use crate::types::event::IbcEvent; +use core::time::Duration; +use ibc::core::ics02_client::client_type::ClientType; +use ibc::core::ics24_host::identifier::ClientId; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::core::traits::client::{HasAnyClientMethods, HasAnyClientTypes}; +use ibc_framework::core::traits::sync::Async; + +use crate::types::message::IbcMessageType; + +pub trait OfaCosmosChain: Async { + type Error: Async; + + type ChainComponents; + + type AnyClient: HasAnyClientMethods< + Timestamp = Timestamp, + Height = Height, + Duration = Duration, + ClientType = ClientType, + >; + + fn emit_event(&self, event: &IbcEvent); + + fn host_height(&self) -> Height; + + fn host_timestamp(&self) -> Timestamp; + + fn get_client_type(&self, client_id: &ClientId) -> Result; + + fn get_any_client_state( + &self, + client_id: &ClientId, + ) -> Result<::AnyClientState, Self::Error>; + + fn get_latest_any_consensus_state( + &self, + client_id: &ClientId, + ) -> Result<::AnyConsensusState, Self::Error>; + + fn get_any_consensus_state_at_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result::AnyConsensusState>, Self::Error>; + + fn get_any_consensus_state_after_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result::AnyConsensusState>, Self::Error>; + + fn get_any_consensus_state_before_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result::AnyConsensusState>, Self::Error>; + + fn set_any_client_state( + &self, + client_id: &ClientId, + client_state: &::AnyClientState, + ) -> Result<(), Self::Error>; + + fn set_any_consensus_state( + &self, + client_id: &ClientId, + consensus_state: &::AnyConsensusState, + ) -> Result<(), Self::Error>; + + fn client_type_mismatch_error(expected_client_type: &ClientType) -> Self::Error; + + fn unknown_message_error(message_type: &IbcMessageType) -> Self::Error; + + fn parse_message_error(message_type: &IbcMessageType) -> Self::Error; + + fn client_frozen_error(client_id: &ClientId) -> Self::Error; + + fn client_expired_error( + client_id: &ClientId, + current_time: &Timestamp, + latest_allowed_update_time: &Timestamp, + ) -> Self::Error; +} diff --git a/crates/ibc-cosmos/src/one_for_all/traits/client.rs b/crates/ibc-cosmos/src/one_for_all/traits/client.rs new file mode 100644 index 0000000000..69dbb595d0 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/traits/client.rs @@ -0,0 +1,75 @@ +use core::time::Duration; +use ibc::clients::ics07_tendermint::client_state::ClientState as TendermintClientState; +use ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TendermintConsensusState; +use ibc::clients::ics07_tendermint::header::Header as TendermintClientHeader; +use ibc::clients::ics07_tendermint::misbehaviour::Misbehaviour as TendermintMisbehavior; +use ibc::core::ics02_client::client_type::ClientType; +use ibc::timestamp::Timestamp; +use ibc::Height; +use ibc_framework::core::traits::sync::Async; + +pub trait OfaCosmosClient: Async { + type AnyClientState: Async; + + type AnyConsensusState: Async; + + type AnyClientHeader: Async; + + type AnyMisbehavior: Async; + + fn client_state_type(client_state: &Self::AnyClientState) -> ClientType; + + fn client_state_is_frozen(client_state: &Self::AnyClientState) -> bool; + + fn client_state_trusting_period(client_state: &Self::AnyClientState) -> Duration; + + fn client_state_latest_height(client_state: &Self::AnyClientState) -> Height; + + fn consensus_state_timestamp(consensus_state: &Self::AnyConsensusState) -> Timestamp; + + fn client_header_height(client_header: &Self::AnyClientHeader) -> Height; + + fn try_into_tendermint_client_state( + client_state: Self::AnyClientState, + ) -> Option; + + fn try_into_tendermint_client_state_ref( + client_state: &Self::AnyClientState, + ) -> Option<&TendermintClientState>; + + fn from_tendermint_client_state(client_state: TendermintClientState) -> Self::AnyClientState; + + fn try_into_tendermint_consensus_state( + consensus_state: Self::AnyConsensusState, + ) -> Option; + + fn try_into_tendermint_consensus_state_ref( + consensus_state: &Self::AnyConsensusState, + ) -> Option<&TendermintConsensusState>; + + fn from_tendermint_consensus_state( + consensus_state: TendermintConsensusState, + ) -> Self::AnyConsensusState; + + fn try_into_tendermint_client_header( + client_header: Self::AnyClientHeader, + ) -> Option; + + fn try_into_tendermint_client_header_ref( + client_header: &Self::AnyClientHeader, + ) -> Option<&TendermintClientHeader>; + + fn from_tendermint_client_header( + client_header: TendermintClientHeader, + ) -> Self::AnyClientHeader; + + fn try_into_tendermint_misbehavior( + misbehavior: Self::AnyMisbehavior, + ) -> Option; + + fn try_into_tendermint_misbehavior_ref( + misbehavior: &Self::AnyMisbehavior, + ) -> Option<&TendermintMisbehavior>; + + fn from_tendermint_misbehavior(misbehavior: TendermintMisbehavior) -> Self::AnyMisbehavior; +} diff --git a/crates/ibc-cosmos/src/one_for_all/traits/mod.rs b/crates/ibc-cosmos/src/one_for_all/traits/mod.rs new file mode 100644 index 0000000000..50598a1adf --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/traits/mod.rs @@ -0,0 +1,2 @@ +pub mod chain; +pub mod client; diff --git a/crates/ibc-cosmos/src/one_for_all/types/chain.rs b/crates/ibc-cosmos/src/one_for_all/types/chain.rs new file mode 100644 index 0000000000..01d25c2315 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/types/chain.rs @@ -0,0 +1,3 @@ +pub struct OfaCosmosChainWrapper { + pub chain: Chain, +} diff --git a/crates/ibc-cosmos/src/one_for_all/types/mod.rs b/crates/ibc-cosmos/src/one_for_all/types/mod.rs new file mode 100644 index 0000000000..28ac57df57 --- /dev/null +++ b/crates/ibc-cosmos/src/one_for_all/types/mod.rs @@ -0,0 +1 @@ +pub mod chain; diff --git a/crates/ibc-cosmos/src/types/event.rs b/crates/ibc-cosmos/src/types/event.rs new file mode 100644 index 0000000000..9aa3c352cd --- /dev/null +++ b/crates/ibc-cosmos/src/types/event.rs @@ -0,0 +1,31 @@ +use ibc::core::ics24_host::identifier::ClientId; +use ibc::Height; +use ibc_framework::core::traits::client::HasAnyClientTypes; + +pub enum IbcEvent +where + AnyClient: HasAnyClientTypes, +{ + UpdateClient(UpdateClientEvent), + Misbehavior(MisbehaviorEvent), +} + +pub struct UpdateClientEvent +where + AnyClient: HasAnyClientTypes, +{ + pub client_id: ClientId, + pub client_type: AnyClient::ClientType, + pub consensus_height: Height, + pub header: AnyClient::AnyClientHeader, +} + +pub struct MisbehaviorEvent +where + AnyClient: HasAnyClientTypes, +{ + pub client_id: ClientId, + pub client_type: AnyClient::ClientType, + pub consensus_height: Height, + pub header: AnyClient::AnyClientHeader, +} diff --git a/crates/ibc-cosmos/src/types/message.rs b/crates/ibc-cosmos/src/types/message.rs new file mode 100644 index 0000000000..6a3161fae7 --- /dev/null +++ b/crates/ibc-cosmos/src/types/message.rs @@ -0,0 +1,35 @@ +use ibc::core::ics24_host::identifier::ClientId; +use ibc::signer::Signer; +use ibc_framework::core::traits::client::HasAnyClientTypes; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum IbcMessageType { + UpdateClient, +} + +pub enum IbcMessage +where + AnyClient: HasAnyClientTypes, +{ + UpdateClient(UpdateClientMessage), +} + +impl IbcMessage +where + AnyClient: HasAnyClientTypes, +{ + pub fn message_type(&self) -> IbcMessageType { + match self { + Self::UpdateClient(_) => IbcMessageType::UpdateClient, + } + } +} + +pub struct UpdateClientMessage +where + AnyClient: HasAnyClientTypes, +{ + pub client_id: ClientId, + pub client_header: AnyClient::AnyClientHeader, + pub signer: Signer, +} diff --git a/crates/ibc-cosmos/src/types/mod.rs b/crates/ibc-cosmos/src/types/mod.rs new file mode 100644 index 0000000000..31912aa380 --- /dev/null +++ b/crates/ibc-cosmos/src/types/mod.rs @@ -0,0 +1,2 @@ +pub mod event; +pub mod message; From 39848bb1df93586a45dbad06f55b38afc2a9c19b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 1 Feb 2023 19:39:53 +0100 Subject: [PATCH 3/4] Fix errors from latest ibc module --- Cargo.lock | 3 +-- Cargo.toml | 1 + .../ibc-cosmos/src/clients/dynamic/client.rs | 5 ++++- .../src/clients/tendermint/client.rs | 5 ++++- .../src/clients/tendermint/update_client.rs | 1 + .../impls/handlers/update_client/combine.rs | 2 +- .../core/impls/handlers/update_client/lift.rs | 2 +- crates/ibc-framework/src/core/traits/client.rs | 18 +++++++++--------- 8 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1045309e30..fb1be12c85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1845,8 +1845,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a730a189bda73e2d2ac215b49fd2c533388b966dd59c9d7550e520f6b9e711" +source = "git+https://github.com/cosmos/ibc-rs.git?branch=soares/relayer-next#3307b5738694b43324d4049204f7a890d0439893" dependencies = [ "bytes", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index b2412e5ea5..254d8de46f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ exclude = [ ] [patch.crates-io] +ibc = { version = "0.27.0", git = "https://github.com/cosmos/ibc-rs.git", branch = "soares/relayer-next" } # tendermint = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" } # tendermint-rpc = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" } # tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" } diff --git a/crates/ibc-cosmos/src/clients/dynamic/client.rs b/crates/ibc-cosmos/src/clients/dynamic/client.rs index 50abf6fa79..b253891bba 100644 --- a/crates/ibc-cosmos/src/clients/dynamic/client.rs +++ b/crates/ibc-cosmos/src/clients/dynamic/client.rs @@ -1,5 +1,6 @@ use core::time::Duration; use ibc::clients::ics07_tendermint::client_state::ClientState as TendermintClientState; +use ibc::clients::ics07_tendermint::client_type as tendermint_client_type; use ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TendermintConsensusState; use ibc::clients::ics07_tendermint::header::Header as TendermintClientHeader; use ibc::clients::ics07_tendermint::misbehaviour::Misbehaviour as TendermintMisbehavior; @@ -105,7 +106,9 @@ impl Prism for DynamicClient { } impl HasClientTypeFor for DynamicClient { - const CLIENT_TYPE: ClientType = ClientType::Tendermint; + fn client_type() -> Self::ClientType { + tendermint_client_type() + } } impl HasHostTypes for DynamicClient { diff --git a/crates/ibc-cosmos/src/clients/tendermint/client.rs b/crates/ibc-cosmos/src/clients/tendermint/client.rs index d9a69af4f4..c4e8b8eda4 100644 --- a/crates/ibc-cosmos/src/clients/tendermint/client.rs +++ b/crates/ibc-cosmos/src/clients/tendermint/client.rs @@ -1,4 +1,5 @@ use core::time::Duration; +use ibc::clients::ics07_tendermint::client_type as tendermint_client_type; use ibc::core::ics02_client::client_state::ClientState; use ibc::core::ics02_client::client_type::ClientType; use ibc::core::ics02_client::consensus_state::ConsensusState; @@ -158,7 +159,9 @@ impl Prism for TendermintClient { } impl HasClientTypeFor for TendermintClient { - const CLIENT_TYPE: ClientType = ClientType::Tendermint; + fn client_type() -> Self::ClientType { + tendermint_client_type() + } } impl HasHostTypes for TendermintClient { diff --git a/crates/ibc-cosmos/src/clients/tendermint/update_client.rs b/crates/ibc-cosmos/src/clients/tendermint/update_client.rs index 779685c284..3584b39310 100644 --- a/crates/ibc-cosmos/src/clients/tendermint/update_client.rs +++ b/crates/ibc-cosmos/src/clients/tendermint/update_client.rs @@ -103,6 +103,7 @@ where })?; let trusted_state = TrustedBlockState { + chain_id: &client_state.chain_id.clone().into(), header_time: trusted_consensus_state.timestamp, height: trusted_block_height, next_validators: &new_client_header.trusted_validator_set, diff --git a/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs b/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs index c03b1c1e98..061314721f 100644 --- a/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs +++ b/crates/ibc-framework/src/core/impls/handlers/update_client/combine.rs @@ -27,7 +27,7 @@ where ) -> Result<(Context::AnyClientState, Context::AnyConsensusState), Context::Error> { let client_type = context.get_client_type(client_id)?; - if client_type == Context::CLIENT_TYPE { + if client_type == Context::client_type() { >::check_client_header_and_update_state( context, client_id, diff --git a/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs b/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs index adeb43beaa..47ad6a6c31 100644 --- a/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs +++ b/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs @@ -25,7 +25,7 @@ where ) -> Result<(Context::AnyClientState, Context::AnyConsensusState), Context::Error> { let client_type = Context::client_state_type(client_state); - if client_type != Context::CLIENT_TYPE {} + if client_type != Context::client_type() {} let client_state = Context::try_from_any_client_state_ref(client_state)?; diff --git a/crates/ibc-framework/src/core/traits/client.rs b/crates/ibc-framework/src/core/traits/client.rs index daae8ca975..307509cb0e 100644 --- a/crates/ibc-framework/src/core/traits/client.rs +++ b/crates/ibc-framework/src/core/traits/client.rs @@ -40,7 +40,7 @@ pub trait HasClientTypes: Async { } pub trait HasClientTypeFor: HasAnyClientTypes { - const CLIENT_TYPE: Self::ClientType; + fn client_type() -> Self::ClientType; } pub trait InjectClientTypeMismatchError: HasError + HasAnyClientTypes { @@ -117,14 +117,14 @@ where client_state: Self::AnyClientState, ) -> Result { Context::try_from(client_state) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn try_from_any_client_state_ref( client_state: &Self::AnyClientState, ) -> Result<&Client::ClientState, Context::Error> { Context::try_from_ref(client_state) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn into_any_consensus_state( @@ -137,14 +137,14 @@ where consensus_state: Self::AnyConsensusState, ) -> Result { Context::try_from(consensus_state) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn try_from_any_consensus_state_ref( consensus_state: &Self::AnyConsensusState, ) -> Result<&Client::ConsensusState, Context::Error> { Context::try_from_ref(consensus_state) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn into_any_client_header(client_header: Client::ClientHeader) -> Self::AnyClientHeader { @@ -155,14 +155,14 @@ where client_header: Self::AnyClientHeader, ) -> Result { Context::try_from(client_header) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn try_from_any_client_header_ref( client_header: &Self::AnyClientHeader, ) -> Result<&Client::ClientHeader, Context::Error> { Context::try_from_ref(client_header) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn into_any_misbehavior(misbehavior: Client::Misbehavior) -> Self::AnyMisbehavior { @@ -173,14 +173,14 @@ where misbehavior: Self::AnyMisbehavior, ) -> Result { Context::try_from(misbehavior) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } fn try_from_any_misbehavior_ref( misbehavior: &Self::AnyMisbehavior, ) -> Result<&Client::Misbehavior, Context::Error> { Context::try_from_ref(misbehavior) - .ok_or_else(|| Context::client_type_mismatch_error(&Self::CLIENT_TYPE)) + .ok_or_else(|| Context::client_type_mismatch_error(&Self::client_type())) } } From 8452094890f8281ef90d9cb56183e64fa51ac52d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 Sep 2023 16:09:41 +0200 Subject: [PATCH 4/4] Fix clippy --- .../src/core/impls/handlers/update_client/lift.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs b/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs index 47ad6a6c31..c9302023c4 100644 --- a/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs +++ b/crates/ibc-framework/src/core/impls/handlers/update_client/lift.rs @@ -25,7 +25,11 @@ where ) -> Result<(Context::AnyClientState, Context::AnyConsensusState), Context::Error> { let client_type = Context::client_state_type(client_state); - if client_type != Context::client_type() {} + let expected_client_type = Context::client_type(); + + if client_type != expected_client_type { + return Err(Context::client_type_mismatch_error(&expected_client_type)); + } let client_state = Context::try_from_any_client_state_ref(client_state)?;