diff --git a/rust/chains/hyperlane-cosmos/src/aggregation_ism.rs b/rust/chains/hyperlane-cosmos/src/aggregation_ism.rs index a17a4ba3a..d18a6577c 100644 --- a/rust/chains/hyperlane-cosmos/src/aggregation_ism.rs +++ b/rust/chains/hyperlane-cosmos/src/aggregation_ism.rs @@ -1,15 +1,17 @@ use std::str::FromStr; use crate::{ - address::CosmosAddress, grpc::WasmProvider, - payloads::aggregate_ism::{ModulesAndThresholdRequest, ModulesAndThresholdResponse}, + payloads::{ + ism_routes::QueryIsmGeneralRequest, + multisig_ism::{VerifyInfoRequest, VerifyInfoRequestInner, VerifyInfoResponse}, + }, ConnectionConf, CosmosProvider, Signer, }; use async_trait::async_trait; use hyperlane_core::{ AggregationIsm, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, - HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, H256, + HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, RawHyperlaneMessage, H256, }; use tracing::instrument; @@ -66,15 +68,27 @@ impl AggregationIsm for CosmosAggregationIsm { &self, message: &HyperlaneMessage, ) -> ChainResult<(Vec, u8)> { - let payload = ModulesAndThresholdRequest::new(message); + let payload = VerifyInfoRequest { + verify_info: VerifyInfoRequestInner { + message: hex::encode(RawHyperlaneMessage::from(message)), + }, + }; - let data = self.provider.grpc().wasm_query(payload, None).await?; - let response: ModulesAndThresholdResponse = serde_json::from_slice(&data)?; + let data = self + .provider + .grpc() + .wasm_query(QueryIsmGeneralRequest { ism: payload }, None) + .await?; + let response: VerifyInfoResponse = serde_json::from_slice(&data)?; + // Note that due to a misnomer in the CosmWasm implementation, the `modules` field is called `validators`. let modules: ChainResult> = response - .modules - .into_iter() - .map(|module| CosmosAddress::from_str(&module).map(|ca| ca.digest())) + .validators + .iter() + // The returned values are Bech32-decoded Cosmos addresses. + // Since they are not EOAs but rather contracts, they are 32 bytes long and + // need to be parsed directly as an `H256`. + .map(|module| H256::from_str(module).map_err(Into::into)) .collect(); Ok((modules?, response.threshold)) diff --git a/rust/chains/hyperlane-cosmos/src/interchain_security_module.rs b/rust/chains/hyperlane-cosmos/src/interchain_security_module.rs index 9e726e562..bfde29f29 100644 --- a/rust/chains/hyperlane-cosmos/src/interchain_security_module.rs +++ b/rust/chains/hyperlane-cosmos/src/interchain_security_module.rs @@ -1,12 +1,14 @@ use async_trait::async_trait; use hyperlane_core::{ ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, - HyperlaneMessage, HyperlaneProvider, InterchainSecurityModule, ModuleType, H256, U256, + HyperlaneMessage, HyperlaneProvider, InterchainSecurityModule, ModuleType, RawHyperlaneMessage, + H256, U256, }; use crate::{ grpc::WasmProvider, payloads::{ + aggregate_ism::{VerifyRequest, VerifyRequestInner, VerifyResponse}, general::EmptyStruct, ism_routes::{QueryIsmGeneralRequest, QueryIsmModuleTypeRequest}, }, @@ -91,6 +93,23 @@ impl InterchainSecurityModule for CosmosInterchainSecurityModule { message: &HyperlaneMessage, metadata: &[u8], ) -> ChainResult> { - Ok(Some(U256::from(1000))) // TODO + let payload = VerifyRequest { + verify: VerifyRequestInner { + metadata: hex::encode(metadata), + message: hex::encode(RawHyperlaneMessage::from(message)), + }, + }; + let data = self + .provider + .grpc() + .wasm_query(QueryIsmGeneralRequest { ism: payload }, None) + .await?; + let response: VerifyResponse = serde_json::from_slice(&data)?; + // We can't simulate the `verify` call in CosmWasm because + // it's not marked as an entrypoint. So we just use the query interface + // and hardcode a gas value - this can be inefficient if one ISM is + // vastly cheaper than another one. + let dummy_gas_value = U256::one(); + Ok(response.verified.then_some(dummy_gas_value)) } } diff --git a/rust/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs b/rust/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs index 7bb5d40d0..8276675ff 100644 --- a/rust/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs +++ b/rust/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs @@ -1,30 +1,17 @@ -use hyperlane_core::{HyperlaneMessage, RawHyperlaneMessage}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] -pub struct ModulesAndThresholdRequest { - modules_and_threshold: ModulesAndThresholdRequestInner, -} - -impl ModulesAndThresholdRequest { - pub fn new(message: &HyperlaneMessage) -> Self { - Self { - modules_and_threshold: ModulesAndThresholdRequestInner { - message: hex::encode(RawHyperlaneMessage::from(message)), - }, - } - } +pub struct VerifyRequest { + pub verify: VerifyRequestInner, } #[derive(Serialize, Deserialize, Debug)] -struct ModulesAndThresholdRequestInner { - /// Hex-encoded Hyperlane message +pub struct VerifyRequestInner { + pub metadata: String, pub message: String, } #[derive(Serialize, Deserialize, Debug)] -pub struct ModulesAndThresholdResponse { - pub threshold: u8, - /// Bech32-encoded module addresses - pub modules: Vec, +pub struct VerifyResponse { + pub verified: bool, } diff --git a/rust/utils/run-locally/src/cosmos/deploy.rs b/rust/utils/run-locally/src/cosmos/deploy.rs index 859f9f05d..25a8d1dae 100644 --- a/rust/utils/run-locally/src/cosmos/deploy.rs +++ b/rust/utils/run-locally/src/cosmos/deploy.rs @@ -113,6 +113,20 @@ pub fn deploy_cw_hyperlane( "hpl_ism_multisig", ); + // deploy ism - aggregation + let ism_aggregate = cli.wasm_init( + &endpoint, + &deployer, + Some(deployer_addr), + codes.hpl_ism_aggregate, + ism::aggregate::InstantiateMsg { + owner: deployer_addr.clone(), + threshold: 1, + isms: vec![ism_multisig.clone()], + }, + "hpl_ism_aggregate", + ); + // deploy merkle hook let hook_merkle = cli.wasm_init( &endpoint, @@ -188,6 +202,7 @@ pub fn deploy_cw_hyperlane( hook_routing, igp, igp_oracle, + ism_aggregate, ism_routing, ism_multisig, mailbox, diff --git a/rust/utils/run-locally/src/cosmos/link.rs b/rust/utils/run-locally/src/cosmos/link.rs index 1cd1efe28..ff3de059f 100644 --- a/rust/utils/run-locally/src/cosmos/link.rs +++ b/rust/utils/run-locally/src/cosmos/link.rs @@ -162,7 +162,7 @@ fn link_network( ism::routing::ExecuteMsg::Set { ism: ism::routing::IsmSet { domain: target_domain, - address: network.deployments.ism_multisig.clone(), + address: network.deployments.ism_aggregate.clone(), }, }, vec![], diff --git a/rust/utils/run-locally/src/cosmos/types.rs b/rust/utils/run-locally/src/cosmos/types.rs index d3a515c4e..7a1575565 100644 --- a/rust/utils/run-locally/src/cosmos/types.rs +++ b/rust/utils/run-locally/src/cosmos/types.rs @@ -42,6 +42,7 @@ pub struct Codes { pub hpl_hook_routing: u64, pub hpl_igp: u64, pub hpl_igp_oracle: u64, + pub hpl_ism_aggregate: u64, pub hpl_ism_multisig: u64, pub hpl_ism_routing: u64, pub hpl_test_mock_ism: u64, @@ -57,6 +58,7 @@ pub struct Deployments { pub hook_routing: String, pub igp: String, pub igp_oracle: String, + pub ism_aggregate: String, pub ism_routing: String, pub ism_multisig: String, pub mailbox: String,