diff --git a/light-client/Cargo.lock b/light-client/Cargo.lock index ebbe61f2..dfc54e99 100644 --- a/light-client/Cargo.lock +++ b/light-client/Cargo.lock @@ -1004,7 +1004,7 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "hermes-cosmos-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-encoding-components", @@ -1018,7 +1018,7 @@ dependencies = [ [[package]] name = "hermes-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", ] @@ -1026,7 +1026,7 @@ dependencies = [ [[package]] name = "hermes-protobuf-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-encoding-components", @@ -1613,15 +1613,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" @@ -1850,7 +1841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.82", diff --git a/relayer/Cargo.lock b/relayer/Cargo.lock index 9a008143..939cc0e7 100644 --- a/relayer/Cargo.lock +++ b/relayer/Cargo.lock @@ -1757,7 +1757,7 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermes-any-counterparty" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "cgp-error-eyre", @@ -1774,7 +1774,7 @@ dependencies = [ [[package]] name = "hermes-async-runtime-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "async-trait", "cgp", @@ -1797,7 +1797,7 @@ dependencies = [ [[package]] name = "hermes-chain-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-chain-type-components", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "hermes-chain-type-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", ] @@ -1816,7 +1816,7 @@ dependencies = [ [[package]] name = "hermes-cosmos-chain-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "bech32 0.9.1", "cgp", @@ -1850,7 +1850,7 @@ dependencies = [ [[package]] name = "hermes-cosmos-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-encoding-components", @@ -1864,7 +1864,7 @@ dependencies = [ [[package]] name = "hermes-cosmos-integration-tests" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "eyre", @@ -1898,7 +1898,7 @@ dependencies = [ [[package]] name = "hermes-cosmos-relayer" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "eyre", @@ -1944,7 +1944,7 @@ dependencies = [ [[package]] name = "hermes-cosmos-test-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hdpath", @@ -1969,7 +1969,7 @@ dependencies = [ [[package]] name = "hermes-cosmos-wasm-relayer" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "eyre", @@ -2021,7 +2021,7 @@ dependencies = [ [[package]] name = "hermes-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", ] @@ -2029,7 +2029,7 @@ dependencies = [ [[package]] name = "hermes-error" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "eyre", @@ -2039,7 +2039,7 @@ dependencies = [ [[package]] name = "hermes-ibc-test-suite" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-logging-components", @@ -2050,7 +2050,7 @@ dependencies = [ [[package]] name = "hermes-logger" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-logging-components", @@ -2062,7 +2062,7 @@ dependencies = [ [[package]] name = "hermes-logging-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", ] @@ -2070,7 +2070,7 @@ dependencies = [ [[package]] name = "hermes-protobuf-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-encoding-components", @@ -2081,7 +2081,7 @@ dependencies = [ [[package]] name = "hermes-relayer-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-chain-components", @@ -2093,7 +2093,7 @@ dependencies = [ [[package]] name = "hermes-relayer-components-extra" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-chain-type-components", @@ -2105,7 +2105,7 @@ dependencies = [ [[package]] name = "hermes-runtime" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-async-runtime-components", @@ -2117,7 +2117,7 @@ dependencies = [ [[package]] name = "hermes-runtime-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", ] @@ -2231,6 +2231,7 @@ dependencies = [ "hermes-relayer-components", "hermes-runtime", "hermes-runtime-components", + "hermes-starknet-chain-components", "hermes-starknet-chain-context", "ibc", "ibc-relayer-types", @@ -2252,7 +2253,7 @@ dependencies = [ [[package]] name = "hermes-test-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-chain-type-components", @@ -2264,7 +2265,7 @@ dependencies = [ [[package]] name = "hermes-tokio-runtime-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "futures", @@ -2278,7 +2279,7 @@ dependencies = [ [[package]] name = "hermes-tracing-logging-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-logging-components", @@ -2290,7 +2291,7 @@ dependencies = [ [[package]] name = "hermes-wasm-client-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "cgp-error-eyre", @@ -2310,7 +2311,7 @@ dependencies = [ [[package]] name = "hermes-wasm-encoding-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "hermes-cosmos-encoding-components", @@ -2324,7 +2325,7 @@ dependencies = [ [[package]] name = "hermes-wasm-test-components" version = "0.1.0" -source = "git+https://github.com/informalsystems/hermes-sdk.git#77bea854d6472e188644a1aa174131f21164a6f5" +source = "git+https://github.com/informalsystems/hermes-sdk.git#621b45a59cba6982a2141327ea58ffacbc491b27" dependencies = [ "cgp", "cgp-error-eyre", diff --git a/relayer/crates/starknet-chain-components/src/components/chain.rs b/relayer/crates/starknet-chain-components/src/components/chain.rs index 86ddfb36..8909a1fa 100644 --- a/relayer/crates/starknet-chain-components/src/components/chain.rs +++ b/relayer/crates/starknet-chain-components/src/components/chain.rs @@ -1,14 +1,18 @@ +use cgp::core::component::WithProvider; +use cgp::core::types::impls::UseDelegatedType; use cgp::prelude::*; pub use hermes_cosmos_chain_components::components::client::{ - ChannelIdTypeComponent, ClientIdTypeComponent, ClientStateFieldsGetterComponent, - ConnectionIdTypeComponent, CreateClientPayloadBuilderComponent, - CreateClientPayloadOptionsTypeComponent, CreateClientPayloadTypeComponent, - OutgoingPacketFieldsReaderComponent, OutgoingPacketTypeComponent, PortIdTypeComponent, - SequenceTypeComponent, TimeTypeComponent, TimeoutTypeComponent, - UpdateClientPayloadBuilderComponent, UpdateClientPayloadTypeComponent, + ChannelIdTypeComponent, ClientIdTypeComponent, ClientStateFieldsComponent, + ClientStateQuerierComponent, ConnectionIdTypeComponent, ConsensusStateQuerierComponent, + CreateClientMessageBuilderComponent, CreateClientMessageOptionsTypeComponent, + CreateClientPayloadBuilderComponent, CreateClientPayloadOptionsTypeComponent, + CreateClientPayloadTypeComponent, OutgoingPacketFieldsReaderComponent, + OutgoingPacketTypeComponent, PortIdTypeComponent, SequenceTypeComponent, TimeTypeComponent, + TimeoutTypeComponent, UpdateClientPayloadBuilderComponent, UpdateClientPayloadTypeComponent, }; use hermes_cosmos_chain_components::impls::packet::packet_fields::CosmosPacketFieldReader; use hermes_cosmos_chain_components::impls::types::chain::ProvideCosmosChainTypes; +use hermes_cosmos_chain_components::impls::types::create_client_options::ProvideNoCreateClientMessageOptionsType; pub use hermes_relayer_components::chain::traits::queries::chain_status::ChainStatusQuerierComponent; pub use hermes_relayer_components::chain::traits::send_message::MessageSenderComponent; pub use hermes_relayer_components::chain::traits::types::chain_id::ChainIdTypeComponent; @@ -34,13 +38,18 @@ pub use hermes_test_components::chain::traits::types::address::AddressTypeCompon pub use hermes_test_components::chain::traits::types::amount::AmountTypeComponent; pub use hermes_test_components::chain::traits::types::denom::DenomTypeComponent; +use crate::components::types::StarknetChainTypes; use crate::impls::contract::call::CallStarknetContract; use crate::impls::contract::declare::DeclareSierraContract; use crate::impls::contract::deploy::DeployStarknetContract; use crate::impls::contract::invoke::InvokeStarknetContract; use crate::impls::contract::message::BuildInvokeContractCall; +use crate::impls::messages::create_client::BuildCreateCometClientMessage; use crate::impls::payload_builders::create_client::BuildStarknetCreateClientPayload; use crate::impls::payload_builders::update_client::BuildStarknetUpdateClientPayload; +use crate::impls::queries::client_state::QueryCometClientState; +use crate::impls::queries::consensus_state::QueryCometConsensusState; +use crate::impls::queries::contract_address::GetContractAddressFromField; use crate::impls::queries::status::QueryStarknetChainStatus; use crate::impls::queries::token_balance::QueryErc20TokenBalance; use crate::impls::send_message::SendCallMessages; @@ -69,6 +78,7 @@ pub use crate::traits::contract::deploy::ContractDeployerComponent; pub use crate::traits::contract::invoke::ContractInvokerComponent; pub use crate::traits::contract::message::InvokeContractMessageBuilderComponent; pub use crate::traits::messages::transfer::TransferTokenMessageBuilderComponent; +pub use crate::traits::queries::address::ContractAddressQuerierComponent; pub use crate::traits::queries::token_balance::TokenBalanceQuerierComponent; pub use crate::traits::transfer::TokenTransferComponent; pub use crate::traits::types::blob::BlobTypeComponent; @@ -115,7 +125,6 @@ define_components! { ]: ProvideStarknetContractTypes, [ - ClientIdTypeComponent, ConnectionIdTypeComponent, ChannelIdTypeComponent, PortIdTypeComponent, @@ -125,10 +134,14 @@ define_components! { TimeoutTypeComponent, ]: ProvideCosmosChainTypes, + [ + ClientIdTypeComponent, + ]: + WithProvider>, [ ClientStateTypeComponent, ConsensusStateTypeComponent, - ClientStateFieldsGetterComponent, + ClientStateFieldsComponent, ]: ProvideStarknetIbcClientTypes, [ @@ -169,9 +182,19 @@ define_components! { TransferErc20Token, TokenBalanceQuerierComponent: QueryErc20TokenBalance, + CreateClientMessageOptionsTypeComponent: + ProvideNoCreateClientMessageOptionsType, CreateClientPayloadBuilderComponent: BuildStarknetCreateClientPayload, + CreateClientMessageBuilderComponent: + BuildCreateCometClientMessage, UpdateClientPayloadBuilderComponent: BuildStarknetUpdateClientPayload, + ClientStateQuerierComponent: + QueryCometClientState, + ConsensusStateQuerierComponent: + QueryCometConsensusState, + ContractAddressQuerierComponent: + GetContractAddressFromField, } } diff --git a/relayer/crates/starknet-chain-components/src/components/mod.rs b/relayer/crates/starknet-chain-components/src/components/mod.rs index 03ba4da6..f011a6b0 100644 --- a/relayer/crates/starknet-chain-components/src/components/mod.rs +++ b/relayer/crates/starknet-chain-components/src/components/mod.rs @@ -1,3 +1,4 @@ pub mod chain; pub mod encoding; pub mod starknet_to_cosmos; +pub mod types; diff --git a/relayer/crates/starknet-chain-components/src/components/starknet_to_cosmos.rs b/relayer/crates/starknet-chain-components/src/components/starknet_to_cosmos.rs index 0fbc1611..01f86ee6 100644 --- a/relayer/crates/starknet-chain-components/src/components/starknet_to_cosmos.rs +++ b/relayer/crates/starknet-chain-components/src/components/starknet_to_cosmos.rs @@ -1,7 +1,9 @@ +use cgp::core::types::impls::WithType; use cgp::prelude::*; use hermes_cosmos_chain_components::components::client::{ - ConsensusStateHeightsQuerierComponent, CreateClientMessageBuilderComponent, - CreateClientMessageOptionsTypeComponent, UpdateClientMessageBuilderComponent, + ClientStateTypeComponent, ConsensusStateHeightsQuerierComponent, ConsensusStateTypeComponent, + CreateClientMessageBuilderComponent, CreateClientMessageOptionsTypeComponent, + UpdateClientMessageBuilderComponent, }; use hermes_cosmos_chain_components::components::cosmos_to_cosmos::CosmosToCosmosComponents; use hermes_relayer_components::chain::traits::queries::client_state::{ @@ -13,6 +15,8 @@ use hermes_relayer_components::chain::traits::queries::consensus_state::{ use crate::impls::starknet_to_cosmos::query_consensus_state_height::QueryStarknetConsensusStateHeightsFromGrpc; use crate::impls::starknet_to_cosmos::update_client_message::BuildStarknetUpdateClientMessage; +use crate::types::cosmos::client_state::CometClientState; +use crate::types::cosmos::consensus_state::CometConsensusState; define_components! { StarknetToCosmosComponents { @@ -25,6 +29,10 @@ define_components! { CreateClientMessageBuilderComponent, ]: CosmosToCosmosComponents, + ClientStateTypeComponent: + WithType, + ConsensusStateTypeComponent: + WithType, UpdateClientMessageBuilderComponent: BuildStarknetUpdateClientMessage, ConsensusStateHeightsQuerierComponent: diff --git a/relayer/crates/starknet-chain-components/src/components/types.rs b/relayer/crates/starknet-chain-components/src/components/types.rs new file mode 100644 index 00000000..893d7d16 --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/components/types.rs @@ -0,0 +1,10 @@ +use cgp::prelude::*; +use hermes_cosmos_chain_components::components::client::ClientIdTypeComponent; + +use crate::types::client_id::ClientId; + +define_components! { + StarknetChainTypes { + ClientIdTypeComponent: ClientId, + } +} diff --git a/relayer/crates/starknet-chain-components/src/impls/messages/create_client.rs b/relayer/crates/starknet-chain-components/src/impls/messages/create_client.rs new file mode 100644 index 00000000..f1475574 --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/impls/messages/create_client.rs @@ -0,0 +1,90 @@ +use core::marker::PhantomData; + +use cgp::prelude::*; +use hermes_cairo_encoding_components::strategy::ViaCairo; +use hermes_cairo_encoding_components::types::as_felt::AsFelt; +use hermes_chain_components::traits::message_builders::create_client::CreateClientMessageBuilder; +use hermes_chain_components::traits::types::create_client::{ + HasCreateClientMessageOptionsType, HasCreateClientPayloadType, +}; +use hermes_chain_components::traits::types::message::HasMessageType; +use hermes_chain_type_components::traits::types::address::HasAddressType; +use hermes_cosmos_chain_components::types::payloads::client::CosmosCreateClientPayload; +use hermes_encoding_components::traits::encode::CanEncode; +use hermes_encoding_components::traits::has_encoding::HasEncoding; +use hermes_encoding_components::traits::types::encoded::HasEncodedType; +use hermes_encoding_components::HList; +use starknet::accounts::Call; +use starknet::core::types::Felt; +use starknet::macros::{selector, short_string}; + +use crate::traits::queries::address::CanQueryContractAddress; +use crate::types::cosmos::client_state::{ClientStatus, CometClientState}; +use crate::types::cosmos::consensus_state::CometConsensusState; +use crate::types::cosmos::height::Height; + +pub struct BuildCreateCometClientMessage; + +impl CreateClientMessageBuilder + for BuildCreateCometClientMessage +where + Chain: HasCreateClientMessageOptionsType + + HasMessageType + + HasAddressType
+ + HasEncoding + + CanQueryContractAddress + + CanRaiseError, + Counterparty: + HasCreateClientPayloadType, + Encoding: HasEncodedType> + + CanEncode + + CanEncode + + CanEncode, Vec]>, +{ + async fn build_create_client_message( + chain: &Chain, + _options: &Chain::CreateClientMessageOptions, + payload: CosmosCreateClientPayload, + ) -> Result { + let encoding = chain.encoding(); + + let contract_address = chain.query_contract_address(PhantomData).await?; + + let height = Height { + revision_number: payload.client_state.latest_height().revision_number(), + revision_height: payload.client_state.latest_height().revision_height(), + }; + + let root = payload.consensus_state.root.into_vec(); + + let client_type = short_string!("07-cometbft"); + + let client_state = CometClientState { + latest_height: height, + trusting_period: payload.client_state.trusting_period.as_secs(), + status: ClientStatus::Active, + }; + + let consensus_state = CometConsensusState { + timestamp: payload.consensus_state.timestamp.unix_timestamp() as u64, + root, + }; + + let raw_client_state = encoding.encode(&client_state).map_err(Chain::raise_error)?; + let raw_consensus_state = encoding + .encode(&consensus_state) + .map_err(Chain::raise_error)?; + + let calldata = encoding + .encode(&HList![client_type, raw_client_state, raw_consensus_state]) + .map_err(Chain::raise_error)?; + + let call = Call { + to: contract_address, + selector: selector!("create_client"), + calldata, + }; + + Ok(call) + } +} diff --git a/relayer/crates/starknet-chain-components/src/impls/messages/mod.rs b/relayer/crates/starknet-chain-components/src/impls/messages/mod.rs new file mode 100644 index 00000000..49c233e5 --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/impls/messages/mod.rs @@ -0,0 +1 @@ +pub mod create_client; diff --git a/relayer/crates/starknet-chain-components/src/impls/mod.rs b/relayer/crates/starknet-chain-components/src/impls/mod.rs index 67b07d84..d89a535b 100644 --- a/relayer/crates/starknet-chain-components/src/impls/mod.rs +++ b/relayer/crates/starknet-chain-components/src/impls/mod.rs @@ -2,6 +2,7 @@ pub mod account; pub mod contract; pub mod encoding; pub mod error; +pub mod messages; pub mod payload_builders; pub mod provider; pub mod queries; diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs b/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs new file mode 100644 index 00000000..89ac655d --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs @@ -0,0 +1,69 @@ +use core::marker::PhantomData; + +use cgp::prelude::*; +use hermes_cairo_encoding_components::strategy::ViaCairo; +use hermes_cairo_encoding_components::types::as_felt::AsFelt; +use hermes_chain_components::traits::queries::client_state::ClientStateQuerier; +use hermes_chain_components::traits::types::client_state::HasClientStateType; +use hermes_chain_components::traits::types::height::HasHeightType; +use hermes_chain_components::traits::types::ibc::HasClientIdType; +use hermes_encoding_components::traits::decode::CanDecode; +use hermes_encoding_components::traits::encode::CanEncode; +use hermes_encoding_components::traits::has_encoding::HasEncoding; +use hermes_encoding_components::traits::types::encoded::HasEncodedType; +use starknet::core::types::Felt; +use starknet::macros::selector; + +use crate::traits::contract::call::CanCallContract; +use crate::traits::queries::address::CanQueryContractAddress; +use crate::traits::types::blob::HasBlobType; +use crate::traits::types::method::HasSelectorType; +use crate::types::client_id::ClientId; +use crate::types::cosmos::client_state::CometClientState; + +pub struct QueryCometClientState; + +impl ClientStateQuerier + for QueryCometClientState +where + Chain: HasClientIdType + + HasHeightType + + CanCallContract + + HasSelectorType + + HasBlobType> + + HasEncoding + + CanQueryContractAddress + + CanRaiseError, + Counterparty: HasClientStateType, + Encoding: CanEncode + + CanDecode> + + CanDecode + + HasEncodedType>, +{ + async fn query_client_state( + chain: &Chain, + _tag: PhantomData, + client_id: &Chain::ClientId, + _height: &Chain::Height, // TODO: figure whether we can perform height specific queries on Starknet + ) -> Result { + let encoding = chain.encoding(); + + let contract_address = chain.query_contract_address(PhantomData).await?; + + let calldata = encoding + .encode(&client_id.sequence) + .map_err(Chain::raise_error)?; + + let output = chain + .call_contract(&contract_address, &selector!("client_state"), &calldata) + .await?; + + let raw_client_state: Vec = encoding.decode(&output).map_err(Chain::raise_error)?; + + let client_state: CometClientState = encoding + .decode(&raw_client_state) + .map_err(Chain::raise_error)?; + + Ok(client_state) + } +} diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs b/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs new file mode 100644 index 00000000..560d458d --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs @@ -0,0 +1,79 @@ +use core::marker::PhantomData; + +use cgp::prelude::*; +use hermes_cairo_encoding_components::strategy::ViaCairo; +use hermes_cairo_encoding_components::types::as_felt::AsFelt; +use hermes_chain_components::traits::queries::consensus_state::ConsensusStateQuerier; +use hermes_chain_components::traits::types::consensus_state::HasConsensusStateType; +use hermes_chain_components::traits::types::height::{HasHeightFields, HasHeightType}; +use hermes_chain_components::traits::types::ibc::HasClientIdType; +use hermes_encoding_components::traits::decode::CanDecode; +use hermes_encoding_components::traits::encode::CanEncode; +use hermes_encoding_components::traits::has_encoding::HasEncoding; +use hermes_encoding_components::traits::types::encoded::HasEncodedType; +use starknet::core::types::Felt; +use starknet::macros::selector; + +use crate::traits::contract::call::CanCallContract; +use crate::traits::queries::address::CanQueryContractAddress; +use crate::traits::types::blob::HasBlobType; +use crate::traits::types::method::HasSelectorType; +use crate::types::client_id::ClientId; +use crate::types::cosmos::consensus_state::CometConsensusState; +use crate::types::cosmos::height::Height; + +pub struct QueryCometConsensusState; + +impl ConsensusStateQuerier + for QueryCometConsensusState +where + Chain: HasClientIdType + + HasHeightType + + CanCallContract + + HasSelectorType + + HasBlobType> + + HasEncoding + + CanQueryContractAddress + + CanRaiseError, + Counterparty: + HasConsensusStateType + HasHeightFields, + Encoding: CanEncode + + CanDecode> + + CanDecode + + HasEncodedType>, +{ + async fn query_consensus_state( + chain: &Chain, + _tag: PhantomData, + client_id: &Chain::ClientId, + consensus_height: &Counterparty::Height, + _query_height: &Chain::Height, // TODO: figure whether we can perform height specific queries on Starknet + ) -> Result { + let encoding = chain.encoding(); + + let contract_address = chain.query_contract_address(PhantomData).await?; + + let calldata = encoding + .encode(&( + client_id.sequence, + Height { + revision_number: Counterparty::revision_number(consensus_height), + revision_height: Counterparty::revision_height(consensus_height), + }, + )) + .map_err(Chain::raise_error)?; + + let output = chain + .call_contract(&contract_address, &selector!("consensus_state"), &calldata) + .await?; + + let raw_consensus_state: Vec = + encoding.decode(&output).map_err(Chain::raise_error)?; + + let consensus_state: CometConsensusState = encoding + .decode(&raw_consensus_state) + .map_err(Chain::raise_error)?; + + Ok(consensus_state) + } +} diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/contract_address.rs b/relayer/crates/starknet-chain-components/src/impls/queries/contract_address.rs new file mode 100644 index 00000000..00257a9b --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/impls/queries/contract_address.rs @@ -0,0 +1,29 @@ +use core::marker::PhantomData; + +use cgp::prelude::*; +use hermes_chain_type_components::traits::types::address::HasAddressType; + +use crate::traits::queries::address::ContractAddressQuerier; + +pub struct GetContractAddressFromField; + +#[derive(Debug)] +pub struct ContractAddressNotFound; + +impl ContractAddressQuerier for GetContractAddressFromField +where + Chain: HasAddressType + + CanRaiseError + + HasField>, + Tag: Async, +{ + async fn query_contract_address( + chain: &Chain, + tag: PhantomData, + ) -> Result { + chain + .get_field(tag) + .clone() + .ok_or_else(|| Chain::raise_error(ContractAddressNotFound)) + } +} diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/mod.rs b/relayer/crates/starknet-chain-components/src/impls/queries/mod.rs index 70b11378..528aa275 100644 --- a/relayer/crates/starknet-chain-components/src/impls/queries/mod.rs +++ b/relayer/crates/starknet-chain-components/src/impls/queries/mod.rs @@ -1,2 +1,5 @@ +pub mod client_state; +pub mod consensus_state; +pub mod contract_address; pub mod status; pub mod token_balance; diff --git a/relayer/crates/starknet-chain-components/src/traits/queries/address.rs b/relayer/crates/starknet-chain-components/src/traits/queries/address.rs new file mode 100644 index 00000000..d28bda4f --- /dev/null +++ b/relayer/crates/starknet-chain-components/src/traits/queries/address.rs @@ -0,0 +1,13 @@ +use core::marker::PhantomData; + +use cgp::prelude::*; +use hermes_chain_type_components::traits::types::address::HasAddressType; + +#[derive_component(ContractAddressQuerierComponent, ContractAddressQuerier)] +#[async_trait] +pub trait CanQueryContractAddress: HasAddressType + HasErrorType { + async fn query_contract_address( + &self, + tag: PhantomData, + ) -> Result; +} diff --git a/relayer/crates/starknet-chain-components/src/traits/queries/mod.rs b/relayer/crates/starknet-chain-components/src/traits/queries/mod.rs index 6ee97613..86b5c989 100644 --- a/relayer/crates/starknet-chain-components/src/traits/queries/mod.rs +++ b/relayer/crates/starknet-chain-components/src/traits/queries/mod.rs @@ -1 +1,2 @@ +pub mod address; pub mod token_balance; diff --git a/relayer/crates/starknet-chain-components/src/types/cosmos/client_state.rs b/relayer/crates/starknet-chain-components/src/types/cosmos/client_state.rs index d6ea8305..c42caae1 100644 --- a/relayer/crates/starknet-chain-components/src/types/cosmos/client_state.rs +++ b/relayer/crates/starknet-chain-components/src/types/cosmos/client_state.rs @@ -19,8 +19,17 @@ pub struct CometClientState { pub status: ClientStatus, } +#[derive(Debug)] +pub enum ClientStatus { + Active, + Expired, + Frozen(Height), +} + pub struct EncodeCometClientState; +pub struct EncodeClientStatus; + delegate_components! { EncodeCometClientState { MutEncoderComponent: CombineEncoders< @@ -47,15 +56,6 @@ impl Transformer for EncodeCometClientState { } } -#[derive(Debug)] -pub enum ClientStatus { - Active, - Expired, - Frozen(Height), -} - -pub struct EncodeClientStatus; - delegate_components! { EncodeClientStatus { [ diff --git a/relayer/crates/starknet-chain-components/src/types/cosmos/height.rs b/relayer/crates/starknet-chain-components/src/types/cosmos/height.rs index e1aa4a83..25a45842 100644 --- a/relayer/crates/starknet-chain-components/src/types/cosmos/height.rs +++ b/relayer/crates/starknet-chain-components/src/types/cosmos/height.rs @@ -8,7 +8,7 @@ use hermes_encoding_components::traits::encode_mut::MutEncoderComponent; use hermes_encoding_components::traits::transform::Transformer; use hermes_encoding_components::HList; -#[derive(Debug, HasField)] +#[derive(Debug, Clone, HasField)] pub struct Height { pub revision_number: u64, pub revision_height: u64, diff --git a/relayer/crates/starknet-chain-context/src/contexts/chain.rs b/relayer/crates/starknet-chain-context/src/contexts/chain.rs index 9cf9e14e..22879af2 100644 --- a/relayer/crates/starknet-chain-context/src/contexts/chain.rs +++ b/relayer/crates/starknet-chain-context/src/contexts/chain.rs @@ -28,6 +28,7 @@ use hermes_relayer_components::chain::traits::send_message::CanSendMessages; use hermes_relayer_components::chain::traits::types::chain_id::ChainIdGetter; use hermes_relayer_components::chain::traits::types::client_state::HasClientStateType; use hermes_relayer_components::chain::traits::types::consensus_state::HasConsensusStateType; +use hermes_relayer_components::chain::traits::types::ibc::HasClientIdType; use hermes_relayer_components::chain::traits::types::packet::HasOutgoingPacketType; use hermes_relayer_components::error::traits::retry::HasRetryableError; use hermes_relayer_components::transaction::traits::poll_tx_response::CanPollTxResponse; @@ -52,12 +53,16 @@ use hermes_starknet_chain_components::traits::contract::invoke::CanInvokeContrac use hermes_starknet_chain_components::traits::provider::{ HasStarknetProvider, StarknetProviderGetterComponent, StarknetProviderTypeComponent, }; +use hermes_starknet_chain_components::traits::queries::address::CanQueryContractAddress; use hermes_starknet_chain_components::traits::queries::token_balance::CanQueryTokenBalance; use hermes_starknet_chain_components::traits::transfer::CanTransferToken; use hermes_starknet_chain_components::traits::types::blob::HasBlobType; use hermes_starknet_chain_components::traits::types::method::HasSelectorType; +use hermes_starknet_chain_components::types::client_id::ClientId; use hermes_starknet_chain_components::types::client_state::WasmStarknetClientState; use hermes_starknet_chain_components::types::consensus_state::WasmStarknetConsensusState; +use hermes_starknet_chain_components::types::cosmos::client_state::CometClientState; +use hermes_starknet_chain_components::types::cosmos::consensus_state::CometConsensusState; use hermes_starknet_test_components::impls::types::wallet::ProvideStarknetWalletType; use hermes_test_components::chain::traits::types::address::HasAddressType; use hermes_test_components::chain::traits::types::wallet::WalletTypeComponent; @@ -77,6 +82,7 @@ pub struct StarknetChain { pub chain_id: Felt, pub rpc_client: Arc>, pub account: SingleOwnerAccount>, LocalWallet>, + pub ibc_client_contract_address: Option, } pub struct StarknetChainContextComponents; @@ -172,6 +178,7 @@ pub trait CanUseStarknetChain: + HasBlobType> + HasClientStateType + HasConsensusStateType + + HasClientIdType + HasOutgoingPacketType + HasStarknetProvider + HasStarknetAccount @@ -188,18 +195,27 @@ pub trait CanUseStarknetChain: + CanTransferToken + HasRetryableError + CanBuildCreateClientPayload + // + CanBuildCreateClientMessage + CanBuildUpdateClientPayload + + CanQueryClientState + + CanQueryConsensusState + + CanQueryContractAddress +where + CosmosChain: HasClientStateType + HasConsensusStateType, { } impl CanUseStarknetChain for StarknetChain {} pub trait CanUseCosmosChainWithStarknet: - CanQueryClientState + HasClientStateType + + HasConsensusStateType + + CanQueryClientState + CanQueryConsensusState + CanBuildCreateClientMessage + CanBuildUpdateClientMessage + CanQueryConsensusStateHeight + + CanBuildCreateClientPayload { } diff --git a/relayer/crates/starknet-chain-context/src/impls/error.rs b/relayer/crates/starknet-chain-context/src/impls/error.rs index ab23fd11..0b499ded 100644 --- a/relayer/crates/starknet-chain-context/src/impls/error.rs +++ b/relayer/crates/starknet-chain-context/src/impls/error.rs @@ -30,6 +30,7 @@ use hermes_runtime::types::error::TokioRuntimeError; use hermes_starknet_chain_components::impls::error::account::RaiseAccountError; use hermes_starknet_chain_components::impls::error::provider::RaiseProviderError; use hermes_starknet_chain_components::impls::error::starknet::RaiseStarknetError; +use hermes_starknet_chain_components::impls::queries::contract_address::ContractAddressNotFound; use hermes_starknet_chain_components::impls::send_message::UnexpectedTransactionTraceType; use hermes_starknet_chain_components::types::event::UnknownEvent; use ibc::core::client::types::error::ClientError; @@ -82,6 +83,7 @@ delegate_components! { InvalidWireType, UnsupportedWireType, RequiredFieldTagNotFound, + ContractAddressNotFound, <'a> UnknownEvent<'a>, <'a, Chain: HasTransactionHashType> TxNoResponseError<'a, Chain>, ]: diff --git a/relayer/crates/starknet-integration-tests/src/contexts/bootstrap.rs b/relayer/crates/starknet-integration-tests/src/contexts/bootstrap.rs index d4eac92a..771f6368 100644 --- a/relayer/crates/starknet-integration-tests/src/contexts/bootstrap.rs +++ b/relayer/crates/starknet-integration-tests/src/contexts/bootstrap.rs @@ -138,6 +138,7 @@ impl ChainDriverBuilder for StarknetBootstrapComponents { chain_id, rpc_client, account, + ibc_client_contract_address: None, }; let chain_driver = StarknetChainDriver { diff --git a/relayer/crates/starknet-integration-tests/src/lib.rs b/relayer/crates/starknet-integration-tests/src/lib.rs index 0f9779b8..4c4e8044 100644 --- a/relayer/crates/starknet-integration-tests/src/lib.rs +++ b/relayer/crates/starknet-integration-tests/src/lib.rs @@ -1 +1,6 @@ +#![recursion_limit = "256"] + pub mod contexts; + +#[cfg(test)] +pub mod tests; diff --git a/relayer/crates/starknet-integration-tests/tests/erc20.rs b/relayer/crates/starknet-integration-tests/src/tests/erc20.rs similarity index 98% rename from relayer/crates/starknet-integration-tests/tests/erc20.rs rename to relayer/crates/starknet-integration-tests/src/tests/erc20.rs index 58f3b48a..70952af0 100644 --- a/relayer/crates/starknet-integration-tests/tests/erc20.rs +++ b/relayer/crates/starknet-integration-tests/src/tests/erc20.rs @@ -15,9 +15,10 @@ use hermes_starknet_chain_components::types::events::erc20::Erc20Event; use hermes_starknet_chain_components::types::messages::erc20::deploy::DeployErc20TokenMessage; use hermes_starknet_chain_context::contexts::encoding::cairo::StarknetCairoEncoding; use hermes_starknet_chain_context::contexts::encoding::event::StarknetEventEncoding; -use hermes_starknet_integration_tests::contexts::bootstrap::StarknetBootstrap; use hermes_test_components::bootstrap::traits::chain::CanBootstrapChain; +use crate::contexts::bootstrap::StarknetBootstrap; + #[test] fn test_erc20_transfer() -> Result<(), Error> { let runtime = init_test_runtime(); diff --git a/relayer/crates/starknet-integration-tests/src/tests/ibc_client.rs b/relayer/crates/starknet-integration-tests/src/tests/ibc_client.rs new file mode 100644 index 00000000..5a454a3b --- /dev/null +++ b/relayer/crates/starknet-integration-tests/src/tests/ibc_client.rs @@ -0,0 +1,220 @@ +use core::marker::PhantomData; +use core::time::Duration; +use std::env::var; +use std::path::PathBuf; +use std::sync::Arc; +use std::time::SystemTime; + +use hermes_chain_components::traits::message_builders::create_client::CanBuildCreateClientMessage; +use hermes_chain_components::traits::payload_builders::create_client::CanBuildCreateClientPayload; +use hermes_chain_components::traits::queries::client_state::CanQueryClientStateWithLatestHeight; +use hermes_chain_components::traits::queries::consensus_state::CanQueryConsensusStateWithLatestHeight; +use hermes_chain_components::traits::send_message::CanSendSingleMessage; +use hermes_cosmos_integration_tests::init::init_test_runtime; +use hermes_cosmos_relayer::contexts::build::CosmosBuilder; +use hermes_cosmos_relayer::contexts::chain::CosmosChain; +use hermes_cosmos_wasm_relayer::context::cosmos_bootstrap::CosmosWithWasmClientBootstrap; +use hermes_encoding_components::traits::encode::CanEncode; +use hermes_error::types::Error; +use hermes_runtime_components::traits::fs::read_file::CanReadFileAsString; +use hermes_starknet_chain_components::impls::encoding::events::CanFilterDecodeEvents; +use hermes_starknet_chain_components::traits::contract::declare::CanDeclareContract; +use hermes_starknet_chain_components::traits::contract::deploy::CanDeployContract; +use hermes_starknet_chain_components::types::cosmos::height::Height; +use hermes_starknet_chain_components::types::cosmos::update::CometUpdateHeader; +use hermes_starknet_chain_components::types::events::create_client::CreateClientEvent; +use hermes_starknet_chain_context::contexts::chain::StarknetChain; +use hermes_starknet_chain_context::contexts::encoding::cairo::StarknetCairoEncoding; +use hermes_starknet_chain_context::contexts::encoding::event::StarknetEventEncoding; +use hermes_test_components::bootstrap::traits::chain::CanBootstrapChain; +use ibc_relayer::chain::cosmos::client::Settings; +use ibc_relayer::config::types::TrustThreshold; +use starknet::accounts::Call; +use starknet::macros::selector; + +use crate::contexts::bootstrap::StarknetBootstrap; + +#[test] +fn test_starknet_comet_client_contract() -> Result<(), Error> { + let runtime = init_test_runtime(); + + runtime.runtime.clone().block_on(async move { + let starknet_chain_command_path = std::env::var("STARKNET_BIN") + .unwrap_or("starknet-devnet".into()) + .into(); + + let wasm_client_code_path = PathBuf::from( + var("STARKNET_WASM_CLIENT_PATH").expect("Wasm blob for Starknet light client is required"), + ); + + let timestamp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs(); + + let starknet_bootstrap = StarknetBootstrap { + runtime: runtime.clone(), + chain_command_path: starknet_chain_command_path, + chain_store_dir: format!("./test-data/{timestamp}/starknet").into(), + }; + + let wasm_client_byte_code = tokio::fs::read(&wasm_client_code_path).await?; + + let cosmos_builder = Arc::new(CosmosBuilder::new_with_default(runtime.clone())); + + let cosmos_bootstrap = Arc::new(CosmosWithWasmClientBootstrap { + runtime: runtime.clone(), + builder: cosmos_builder, + should_randomize_identifiers: true, + chain_store_dir: format!("./test-data/{timestamp}/cosmos").into(), + chain_command_path: "simd".into(), + account_prefix: "cosmos".into(), + staking_denom: "stake".into(), + transfer_denom: "coin".into(), + wasm_client_byte_code, + governance_proposal_authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn".into(), // TODO: don't hard code this + }); + + let mut starknet_chain_driver = starknet_bootstrap.bootstrap_chain("starknet").await?; + + let starknet_chain = &mut starknet_chain_driver.chain; + + let cosmos_chain_driver = cosmos_bootstrap.bootstrap_chain("cosmos").await?; + + let cosmos_chain = &cosmos_chain_driver.chain; + + let comet_client_class_hash = { + let contract_path = std::env::var("COMET_CLIENT_CONTRACT")?; + + let contract_str = runtime.read_file_as_string(&contract_path.into()).await?; + + let contract = serde_json::from_str(&contract_str)?; + + let class_hash = starknet_chain.declare_contract(&contract).await?; + + println!("declared class: {:?}", class_hash); + + class_hash + }; + + let comet_client_address = starknet_chain + .deploy_contract(&comet_client_class_hash, false, &Vec::new()) + .await?; + + println!( + "deployed Comet client contract to address: {:?}", + comet_client_address + ); + + starknet_chain.ibc_client_contract_address = Some(comet_client_address); + + let event_encoding = StarknetEventEncoding { + erc20_hashes: Default::default(), + ics20_hashes: Default::default(), + ibc_client_hashes: [comet_client_class_hash].into(), + }; + + let create_client_settings = Settings { + max_clock_drift: Duration::from_secs(40), + trusting_period: Some(Duration::from_secs(60 * 60)), + trust_threshold: TrustThreshold::ONE_THIRD, + }; + + let create_client_payload_1 = >::build_create_client_payload(cosmos_chain, &create_client_settings).await?; + + let height_1 = create_client_payload_1.client_state.latest_height(); + + let root_1 = create_client_payload_1.consensus_state.root.clone().into_vec(); + + let client_id = { + let message = > + ::build_create_client_message(starknet_chain, &(), create_client_payload_1).await?; + + let events = starknet_chain.send_message(message).await?; + + let create_client_event: CreateClientEvent = event_encoding + .filter_decode_events(&events)? + .into_iter() + .next() + .unwrap(); + + let client_id = create_client_event.client_id; + + println!("created client on Starknet: {:?}", client_id); + + client_id + }; + + { + let consensus_state = starknet_chain.query_consensus_state_with_latest_height( + PhantomData::, + &client_id, + &height_1, + ) + .await?; + + println!("queried consensus state: {consensus_state:?}"); + + assert_eq!(consensus_state.root, root_1); + } + + let create_client_payload_2 = >::build_create_client_payload(cosmos_chain, &create_client_settings).await?; + let root_2 = create_client_payload_2.consensus_state.root.into_vec(); + + { + let message = { + let height_2 = Height { + revision_number: create_client_payload_2.client_state.latest_height().revision_number(), + revision_height: create_client_payload_2.client_state.latest_height().revision_height(), + }; + + let update_header = CometUpdateHeader { + trusted_height: Height { + revision_number: height_1.revision_number(), + revision_height: height_1.revision_height(), + }, + target_height: height_2, + time: create_client_payload_2.consensus_state.timestamp.unix_timestamp() as u64, + root: root_2.clone(), + }; + + let raw_header = StarknetCairoEncoding.encode(&update_header)?; + + let calldata = StarknetCairoEncoding.encode(&(&client_id, raw_header))?; + + Call { + to: comet_client_address, + selector: selector!("update_client"), + calldata, + } + }; + + let events = starknet_chain.send_message(message).await?; + + println!("update client events: {:?}", events); + } + + { + let client_state = starknet_chain.query_client_state_with_latest_height( + PhantomData::, &client_id + ) + .await?; + + println!("queried client state: {client_state:?}"); + } + + { + let consensus_state = starknet_chain.query_consensus_state_with_latest_height( + PhantomData::, + &client_id, + &create_client_payload_2.client_state.latest_height(), + ) + .await?; + + println!("queried consensus state: {consensus_state:?}"); + + assert_eq!(consensus_state.root, root_2); + } + + Ok(()) + }) +} diff --git a/relayer/crates/starknet-integration-tests/tests/ics20.rs b/relayer/crates/starknet-integration-tests/src/tests/ics20.rs similarity index 99% rename from relayer/crates/starknet-integration-tests/tests/ics20.rs rename to relayer/crates/starknet-integration-tests/src/tests/ics20.rs index 1a9dc55a..f5cad420 100644 --- a/relayer/crates/starknet-integration-tests/tests/ics20.rs +++ b/relayer/crates/starknet-integration-tests/src/tests/ics20.rs @@ -19,11 +19,12 @@ use hermes_starknet_chain_components::types::messages::ibc::ibc_transfer::{ use hermes_starknet_chain_components::types::messages::ibc::packet::Packet; use hermes_starknet_chain_context::contexts::encoding::cairo::StarknetCairoEncoding; use hermes_starknet_chain_context::contexts::encoding::event::StarknetEventEncoding; -use hermes_starknet_integration_tests::contexts::bootstrap::StarknetBootstrap; use hermes_test_components::bootstrap::traits::chain::CanBootstrapChain; use starknet::accounts::Call; use starknet::macros::selector; +use crate::contexts::bootstrap::StarknetBootstrap; + #[test] fn test_starknet_ics20_contract() -> Result<(), Error> { let runtime = init_test_runtime(); diff --git a/relayer/crates/starknet-integration-tests/tests/light_client.rs b/relayer/crates/starknet-integration-tests/src/tests/light_client.rs similarity index 94% rename from relayer/crates/starknet-integration-tests/tests/light_client.rs rename to relayer/crates/starknet-integration-tests/src/tests/light_client.rs index a6cbda01..96319b2e 100644 --- a/relayer/crates/starknet-integration-tests/tests/light_client.rs +++ b/relayer/crates/starknet-integration-tests/src/tests/light_client.rs @@ -1,5 +1,4 @@ -#![recursion_limit = "256"] - +use core::marker::PhantomData; use std::env::var; use std::path::PathBuf; use std::sync::Arc; @@ -30,9 +29,9 @@ use hermes_relayer_components::relay::traits::client_creator::CanCreateClient; use hermes_relayer_components::relay::traits::target::DestinationTarget; use hermes_relayer_components::relay::traits::update_client_message_builder::CanSendTargetUpdateClientMessage; use hermes_runtime_components::traits::sleep::CanSleep; +use hermes_starknet_chain_components::types::client_id::ClientId as StarknetClientId; use hermes_starknet_chain_components::types::payloads::client::StarknetCreateClientPayloadOptions; use hermes_starknet_chain_context::contexts::chain::StarknetChain; -use hermes_starknet_integration_tests::contexts::bootstrap::StarknetBootstrap; use hermes_starknet_relayer::contexts::starknet_to_cosmos_relay::StarknetToCosmosRelay; use hermes_test_components::bootstrap::traits::chain::CanBootstrapChain; use hermes_test_components::chain_driver::traits::types::chain::HasChain; @@ -44,6 +43,9 @@ use ibc_relayer::config::types::TrustThreshold; use ibc_relayer_types::core::ics04_channel::channel::Ordering; use ibc_relayer_types::Height; use sha2::{Digest, Sha256}; +use starknet::macros::short_string; + +use crate::contexts::bootstrap::StarknetBootstrap; #[test] fn test_starknet_light_client() -> Result<(), Error> { @@ -114,14 +116,18 @@ fn test_starknet_light_client() -> Result<(), Error> { runtime: runtime.clone(), src_chain: starknet_chain.clone(), dst_chain: cosmos_chain.clone(), - src_client_id: client_id.clone(), // TODO: stub + // TODO: stub + src_client_id: StarknetClientId { + client_type: short_string!("cometbft"), + sequence: 1, + }, dst_client_id: client_id.clone(), }; { let client_state = - >::query_client_state( - cosmos_chain, + cosmos_chain.query_client_state( + PhantomData::, &client_id, &cosmos_chain.query_chain_height().await?, ) @@ -130,8 +136,8 @@ fn test_starknet_light_client() -> Result<(), Error> { let client_height = client_state.client_state.latest_height.revision_height(); let consensus_state = - >::query_consensus_state( - cosmos_chain, + cosmos_chain.query_consensus_state( + PhantomData::, &client_id, &client_height, &cosmos_chain.query_chain_height().await?, @@ -161,8 +167,8 @@ fn test_starknet_light_client() -> Result<(), Error> { .await?; let consensus_state = - >::query_consensus_state( - cosmos_chain, + cosmos_chain.query_consensus_state( + PhantomData::, &client_id, &starknet_status.height, &cosmos_chain.query_chain_height().await?, diff --git a/relayer/crates/starknet-integration-tests/src/tests/mod.rs b/relayer/crates/starknet-integration-tests/src/tests/mod.rs new file mode 100644 index 00000000..255a6f7a --- /dev/null +++ b/relayer/crates/starknet-integration-tests/src/tests/mod.rs @@ -0,0 +1,4 @@ +pub mod erc20; +pub mod ibc_client; +pub mod ics20; +pub mod light_client; diff --git a/relayer/crates/starknet-integration-tests/tests/ibc_client.rs b/relayer/crates/starknet-integration-tests/tests/ibc_client.rs deleted file mode 100644 index 0cfeb35d..00000000 --- a/relayer/crates/starknet-integration-tests/tests/ibc_client.rs +++ /dev/null @@ -1,206 +0,0 @@ -use std::time::{SystemTime, UNIX_EPOCH}; - -use hermes_chain_components::traits::send_message::CanSendSingleMessage; -use hermes_cosmos_integration_tests::init::init_test_runtime; -use hermes_encoding_components::traits::decode::CanDecode; -use hermes_encoding_components::traits::encode::CanEncode; -use hermes_encoding_components::HList; -use hermes_error::types::Error; -use hermes_runtime_components::traits::fs::read_file::CanReadFileAsString; -use hermes_starknet_chain_components::impls::encoding::events::CanFilterDecodeEvents; -use hermes_starknet_chain_components::traits::contract::call::CanCallContract; -use hermes_starknet_chain_components::traits::contract::declare::CanDeclareContract; -use hermes_starknet_chain_components::traits::contract::deploy::CanDeployContract; -use hermes_starknet_chain_components::types::cosmos::client_state::{ - ClientStatus, CometClientState, -}; -use hermes_starknet_chain_components::types::cosmos::consensus_state::CometConsensusState; -use hermes_starknet_chain_components::types::cosmos::height::Height; -use hermes_starknet_chain_components::types::cosmos::update::CometUpdateHeader; -use hermes_starknet_chain_components::types::events::create_client::CreateClientEvent; -use hermes_starknet_chain_context::contexts::encoding::cairo::StarknetCairoEncoding; -use hermes_starknet_chain_context::contexts::encoding::event::StarknetEventEncoding; -use hermes_starknet_integration_tests::contexts::bootstrap::StarknetBootstrap; -use hermes_test_components::bootstrap::traits::chain::CanBootstrapChain; -use starknet::accounts::Call; -use starknet::core::types::Felt; -use starknet::macros::{selector, short_string}; - -#[test] -fn test_starknet_comet_client_contract() -> Result<(), Error> { - let runtime = init_test_runtime(); - - runtime.runtime.clone().block_on(async move { - let chain_command_path = std::env::var("STARKNET_BIN") - .unwrap_or("starknet-devnet".into()) - .into(); - - let timestamp = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH)? - .as_secs(); - - let bootstrap = StarknetBootstrap { - runtime: runtime.clone(), - chain_command_path, - chain_store_dir: format!("./test-data/{timestamp}").into(), - }; - - let chain_driver = bootstrap.bootstrap_chain("starknet").await?; - - let chain = &chain_driver.chain; - - let comet_client_class_hash = { - let contract_path = std::env::var("COMET_CLIENT_CONTRACT")?; - - let contract_str = runtime.read_file_as_string(&contract_path.into()).await?; - - let contract = serde_json::from_str(&contract_str)?; - - let class_hash = chain.declare_contract(&contract).await?; - - println!("declared class: {:?}", class_hash); - - class_hash - }; - - let comet_client_address = chain - .deploy_contract(&comet_client_class_hash, false, &Vec::new()) - .await?; - - println!( - "deployed Comet client contract to address: {:?}", - comet_client_address - ); - - let event_encoding = StarknetEventEncoding { - erc20_hashes: Default::default(), - ics20_hashes: Default::default(), - ibc_client_hashes: [comet_client_class_hash].into(), - }; - - let client_id = { - let message = { - let client_type = short_string!("07-cometbft"); - - let height = Height { - revision_number: 0, - revision_height: 1, - }; - - let client_state = CometClientState { - latest_height: height, - trusting_period: 3600, - status: ClientStatus::Active, - }; - - let consensus_state = CometConsensusState { - timestamp: SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() - 10, - root: vec![1, 2, 3], - }; - - let raw_client_state = StarknetCairoEncoding.encode(&client_state)?; - let raw_consensus_state = StarknetCairoEncoding.encode(&consensus_state)?; - - let calldata = StarknetCairoEncoding.encode(&HList![ - client_type, - raw_client_state, - raw_consensus_state - ])?; - - Call { - to: comet_client_address, - selector: selector!("create_client"), - calldata, - } - }; - - let events = chain.send_message(message).await?; - - let create_client_event: CreateClientEvent = event_encoding - .filter_decode_events(&events)? - .into_iter() - .next() - .unwrap(); - - let client_id = create_client_event.client_id; - - println!("created client on Starknet: {:?}", client_id); - - client_id - }; - - { - let message = { - let update_header = CometUpdateHeader { - trusted_height: Height { - revision_number: 0, - revision_height: 1, - }, - target_height: Height { - revision_number: 0, - revision_height: 2, - }, - time: SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() - 10, - root: vec![4, 5, 6], - }; - - let raw_header = StarknetCairoEncoding.encode(&update_header)?; - - let calldata = StarknetCairoEncoding.encode(&(&client_id, raw_header))?; - - Call { - to: comet_client_address, - selector: selector!("update_client"), - calldata, - } - }; - - let events = chain.send_message(message).await?; - - println!("update client events: {:?}", events); - } - - { - let output = chain - .call_contract( - &comet_client_address, - &selector!("client_state"), - &StarknetCairoEncoding.encode(&client_id.sequence)?, - ) - .await?; - - let raw_client_state: Vec = StarknetCairoEncoding.decode(&output)?; - - let client_state: CometClientState = StarknetCairoEncoding.decode(&raw_client_state)?; - - println!("queried client state: {client_state:?}"); - } - - { - let output = chain - .call_contract( - &comet_client_address, - &selector!("consensus_state"), - &StarknetCairoEncoding.encode(&( - client_id.sequence, - Height { - revision_number: 0, - revision_height: 2, - }, - ))?, - ) - .await?; - - let raw_consensus_state: Vec = StarknetCairoEncoding.decode(&output)?; - - let consensus_state: CometConsensusState = - StarknetCairoEncoding.decode(&raw_consensus_state)?; - - println!("queried consensus state: {consensus_state:?}"); - - assert_eq!(consensus_state.root, vec![4, 5, 6]); - } - - Ok(()) - }) -} diff --git a/relayer/crates/starknet-relayer/Cargo.toml b/relayer/crates/starknet-relayer/Cargo.toml index 74f61f96..5416c415 100644 --- a/relayer/crates/starknet-relayer/Cargo.toml +++ b/relayer/crates/starknet-relayer/Cargo.toml @@ -10,17 +10,18 @@ rust-version = { workspace = true } readme = "README.md" [dependencies] -cgp = { workspace = true } -ibc = { workspace = true } -ibc-relayer-types = { workspace = true } -hermes-error = { workspace = true } -hermes-runtime = { workspace = true } -hermes-runtime-components = { workspace = true } -hermes-logging-components = { workspace = true } -hermes-encoding-components = { workspace = true } -hermes-logger = { workspace = true } -hermes-relayer-components = { workspace = true } -hermes-cosmos-relayer = { workspace = true } -hermes-starknet-chain-context = { workspace = true } +cgp = { workspace = true } +ibc = { workspace = true } +ibc-relayer-types = { workspace = true } +hermes-error = { workspace = true } +hermes-runtime = { workspace = true } +hermes-runtime-components = { workspace = true } +hermes-logging-components = { workspace = true } +hermes-encoding-components = { workspace = true } +hermes-logger = { workspace = true } +hermes-relayer-components = { workspace = true } +hermes-cosmos-relayer = { workspace = true } +hermes-starknet-chain-context = { workspace = true } +hermes-starknet-chain-components = { workspace = true } eyre = { workspace = true } diff --git a/relayer/crates/starknet-relayer/src/contexts/starknet_to_cosmos_relay.rs b/relayer/crates/starknet-relayer/src/contexts/starknet_to_cosmos_relay.rs index d3755881..ebb25c63 100644 --- a/relayer/crates/starknet-relayer/src/contexts/starknet_to_cosmos_relay.rs +++ b/relayer/crates/starknet-relayer/src/contexts/starknet_to_cosmos_relay.rs @@ -22,8 +22,9 @@ use hermes_runtime::types::runtime::HermesRuntime; use hermes_runtime_components::traits::runtime::{ ProvideDefaultRuntimeField, RuntimeGetterComponent, RuntimeTypeComponent, }; +use hermes_starknet_chain_components::types::client_id::ClientId as StarknetClientId; use hermes_starknet_chain_context::contexts::chain::StarknetChain; -use ibc_relayer_types::core::ics24_host::identifier::ClientId; +use ibc_relayer_types::core::ics24_host::identifier::ClientId as CosmosClientId; use crate::impls::error::HandleStarknetRelayError; @@ -32,8 +33,8 @@ pub struct StarknetToCosmosRelay { pub runtime: HermesRuntime, pub src_chain: StarknetChain, pub dst_chain: CosmosChain, - pub src_client_id: ClientId, - pub dst_client_id: ClientId, + pub src_client_id: StarknetClientId, + pub dst_client_id: CosmosClientId, } pub struct StarknetToCosmosRelayComponents; @@ -83,11 +84,11 @@ impl ProvideRelayChains for StarknetToCosmosRelayComponen &relay.dst_chain } - fn src_client_id(relay: &StarknetToCosmosRelay) -> &ClientId { + fn src_client_id(relay: &StarknetToCosmosRelay) -> &StarknetClientId { &relay.src_client_id } - fn dst_client_id(relay: &StarknetToCosmosRelay) -> &ClientId { + fn dst_client_id(relay: &StarknetToCosmosRelay) -> &CosmosClientId { &relay.dst_client_id } }