Skip to content

Commit c2cf7be

Browse files
authored
feat(cosmos): ism dry-run (#3077)
### Description Implements `dry_run_verify` for the aggregation ISM on cosmwasm. One remaining issue is that the estimated gas is hardcoded to `1`, because we're actually [just querying](https://github.com/many-things/cw-hyperlane/blob/37fea49429108d0cad46c64c3c1ebc467817ff8c/contracts/isms/aggregate/src/lib.rs#L108) via rpc rather than simulating a tx. The `verify` tx isn't marked as a contract [entrypoint](https://book.cosmwasm.com/basics/entry-points.html) so it can't be called from outside iiuc. (here's the [verify](https://github.com/many-things/cw-hyperlane/blob/37fea49429108d0cad46c64c3c1ebc467817ff8c/contracts/isms/aggregate/src/lib.rs#L124) fn for reference). Worth mentioning that the query interface for the aggregation ISM is named incorrectly - it should return fields called `threshold` and `modules`, but instead copies the response from the multisig ISM and returns `threshold` and `validators`. This can be particularly misleading because validators have 20-bytes long addresses, whereas modules (contracts) have 32-bytes long addresses. ### Related issues - Fixes hyperlane-xyz/issues#807 ### Backward compatibility yes ### Testing E2E. The ISM setup is `routing` -> `aggregation (1/1)` -> `multisig (1/1)`
1 parent f73ee0b commit c2cf7be

File tree

6 files changed

+68
-31
lines changed

6 files changed

+68
-31
lines changed

rust/chains/hyperlane-cosmos/src/aggregation_ism.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
use std::str::FromStr;
22

33
use crate::{
4-
address::CosmosAddress,
54
grpc::WasmProvider,
6-
payloads::aggregate_ism::{ModulesAndThresholdRequest, ModulesAndThresholdResponse},
5+
payloads::{
6+
ism_routes::QueryIsmGeneralRequest,
7+
multisig_ism::{VerifyInfoRequest, VerifyInfoRequestInner, VerifyInfoResponse},
8+
},
79
ConnectionConf, CosmosProvider, Signer,
810
};
911
use async_trait::async_trait;
1012
use hyperlane_core::{
1113
AggregationIsm, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract,
12-
HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, H256,
14+
HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, RawHyperlaneMessage, H256,
1315
};
1416
use tracing::instrument;
1517

@@ -66,15 +68,27 @@ impl AggregationIsm for CosmosAggregationIsm {
6668
&self,
6769
message: &HyperlaneMessage,
6870
) -> ChainResult<(Vec<H256>, u8)> {
69-
let payload = ModulesAndThresholdRequest::new(message);
71+
let payload = VerifyInfoRequest {
72+
verify_info: VerifyInfoRequestInner {
73+
message: hex::encode(RawHyperlaneMessage::from(message)),
74+
},
75+
};
7076

71-
let data = self.provider.grpc().wasm_query(payload, None).await?;
72-
let response: ModulesAndThresholdResponse = serde_json::from_slice(&data)?;
77+
let data = self
78+
.provider
79+
.grpc()
80+
.wasm_query(QueryIsmGeneralRequest { ism: payload }, None)
81+
.await?;
82+
let response: VerifyInfoResponse = serde_json::from_slice(&data)?;
7383

84+
// Note that due to a misnomer in the CosmWasm implementation, the `modules` field is called `validators`.
7485
let modules: ChainResult<Vec<H256>> = response
75-
.modules
76-
.into_iter()
77-
.map(|module| CosmosAddress::from_str(&module).map(|ca| ca.digest()))
86+
.validators
87+
.iter()
88+
// The returned values are Bech32-decoded Cosmos addresses.
89+
// Since they are not EOAs but rather contracts, they are 32 bytes long and
90+
// need to be parsed directly as an `H256`.
91+
.map(|module| H256::from_str(module).map_err(Into::into))
7892
.collect();
7993

8094
Ok((modules?, response.threshold))

rust/chains/hyperlane-cosmos/src/interchain_security_module.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use async_trait::async_trait;
22
use hyperlane_core::{
33
ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain,
4-
HyperlaneMessage, HyperlaneProvider, InterchainSecurityModule, ModuleType, H256, U256,
4+
HyperlaneMessage, HyperlaneProvider, InterchainSecurityModule, ModuleType, RawHyperlaneMessage,
5+
H256, U256,
56
};
67

78
use crate::{
89
grpc::WasmProvider,
910
payloads::{
11+
aggregate_ism::{VerifyRequest, VerifyRequestInner, VerifyResponse},
1012
general::EmptyStruct,
1113
ism_routes::{QueryIsmGeneralRequest, QueryIsmModuleTypeRequest},
1214
},
@@ -91,6 +93,23 @@ impl InterchainSecurityModule for CosmosInterchainSecurityModule {
9193
message: &HyperlaneMessage,
9294
metadata: &[u8],
9395
) -> ChainResult<Option<U256>> {
94-
Ok(Some(U256::from(1000))) // TODO
96+
let payload = VerifyRequest {
97+
verify: VerifyRequestInner {
98+
metadata: hex::encode(metadata),
99+
message: hex::encode(RawHyperlaneMessage::from(message)),
100+
},
101+
};
102+
let data = self
103+
.provider
104+
.grpc()
105+
.wasm_query(QueryIsmGeneralRequest { ism: payload }, None)
106+
.await?;
107+
let response: VerifyResponse = serde_json::from_slice(&data)?;
108+
// We can't simulate the `verify` call in CosmWasm because
109+
// it's not marked as an entrypoint. So we just use the query interface
110+
// and hardcode a gas value - this can be inefficient if one ISM is
111+
// vastly cheaper than another one.
112+
let dummy_gas_value = U256::one();
113+
Ok(response.verified.then_some(dummy_gas_value))
95114
}
96115
}
Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,17 @@
1-
use hyperlane_core::{HyperlaneMessage, RawHyperlaneMessage};
21
use serde::{Deserialize, Serialize};
32

43
#[derive(Serialize, Deserialize, Debug)]
5-
pub struct ModulesAndThresholdRequest {
6-
modules_and_threshold: ModulesAndThresholdRequestInner,
7-
}
8-
9-
impl ModulesAndThresholdRequest {
10-
pub fn new(message: &HyperlaneMessage) -> Self {
11-
Self {
12-
modules_and_threshold: ModulesAndThresholdRequestInner {
13-
message: hex::encode(RawHyperlaneMessage::from(message)),
14-
},
15-
}
16-
}
4+
pub struct VerifyRequest {
5+
pub verify: VerifyRequestInner,
176
}
187

198
#[derive(Serialize, Deserialize, Debug)]
20-
struct ModulesAndThresholdRequestInner {
21-
/// Hex-encoded Hyperlane message
9+
pub struct VerifyRequestInner {
10+
pub metadata: String,
2211
pub message: String,
2312
}
2413

2514
#[derive(Serialize, Deserialize, Debug)]
26-
pub struct ModulesAndThresholdResponse {
27-
pub threshold: u8,
28-
/// Bech32-encoded module addresses
29-
pub modules: Vec<String>,
15+
pub struct VerifyResponse {
16+
pub verified: bool,
3017
}

rust/utils/run-locally/src/cosmos/deploy.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,20 @@ pub fn deploy_cw_hyperlane(
113113
"hpl_ism_multisig",
114114
);
115115

116+
// deploy ism - aggregation
117+
let ism_aggregate = cli.wasm_init(
118+
&endpoint,
119+
&deployer,
120+
Some(deployer_addr),
121+
codes.hpl_ism_aggregate,
122+
ism::aggregate::InstantiateMsg {
123+
owner: deployer_addr.clone(),
124+
threshold: 1,
125+
isms: vec![ism_multisig.clone()],
126+
},
127+
"hpl_ism_aggregate",
128+
);
129+
116130
// deploy merkle hook
117131
let hook_merkle = cli.wasm_init(
118132
&endpoint,
@@ -188,6 +202,7 @@ pub fn deploy_cw_hyperlane(
188202
hook_routing,
189203
igp,
190204
igp_oracle,
205+
ism_aggregate,
191206
ism_routing,
192207
ism_multisig,
193208
mailbox,

rust/utils/run-locally/src/cosmos/link.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn link_network(
162162
ism::routing::ExecuteMsg::Set {
163163
ism: ism::routing::IsmSet {
164164
domain: target_domain,
165-
address: network.deployments.ism_multisig.clone(),
165+
address: network.deployments.ism_aggregate.clone(),
166166
},
167167
},
168168
vec![],

rust/utils/run-locally/src/cosmos/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub struct Codes {
4242
pub hpl_hook_routing: u64,
4343
pub hpl_igp: u64,
4444
pub hpl_igp_oracle: u64,
45+
pub hpl_ism_aggregate: u64,
4546
pub hpl_ism_multisig: u64,
4647
pub hpl_ism_routing: u64,
4748
pub hpl_test_mock_ism: u64,
@@ -57,6 +58,7 @@ pub struct Deployments {
5758
pub hook_routing: String,
5859
pub igp: String,
5960
pub igp_oracle: String,
61+
pub ism_aggregate: String,
6062
pub ism_routing: String,
6163
pub ism_multisig: String,
6264
pub mailbox: String,

0 commit comments

Comments
 (0)