1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
pub mod aggregate;
pub mod multisig;
pub mod routing;

use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, CustomQuery, HexBinary, QuerierWrapper, StdResult};

#[cw_serde]
#[repr(u32)]
pub enum IsmType {
    Unused = 0,
    Routing = 1,
    Aggregation = 2,
    LegacyMultisig = 3,
    MerkleRootMultisig = 4,
    MessageIdMultisig = 5,
    Null = 6, // used with relayer carrying no metadata
    CcipRead = 7,
}

#[cw_serde]
#[derive(QueryResponses)]
pub enum IsmQueryMsg {
    #[returns(ModuleTypeResponse)]
    ModuleType {},

    #[returns(VerifyResponse)]
    Verify {
        metadata: HexBinary,
        message: HexBinary,
    },

    #[returns(VerifyInfoResponse)]
    VerifyInfo { message: HexBinary },
}

impl IsmQueryMsg {
    pub fn wrap(self) -> ExpectedIsmQueryMsg {
        ExpectedIsmQueryMsg::Ism(self)
    }
}

#[cw_serde]
#[derive(QueryResponses)]
#[query_responses(nested)]
pub enum ExpectedIsmQueryMsg {
    Ism(IsmQueryMsg),
}

#[cw_serde]
#[derive(QueryResponses)]
#[query_responses(nested)]
pub enum ExpectedIsmSpecifierQueryMsg {
    IsmSpecifier(IsmSpecifierQueryMsg),
}

#[cw_serde]
#[derive(QueryResponses)]
pub enum IsmSpecifierQueryMsg {
    #[returns(InterchainSecurityModuleResponse)]
    InterchainSecurityModule(),
}

impl IsmSpecifierQueryMsg {
    pub fn wrap(self) -> ExpectedIsmSpecifierQueryMsg {
        ExpectedIsmSpecifierQueryMsg::IsmSpecifier(self)
    }
}

#[cw_serde]
pub struct ModuleTypeResponse {
    #[serde(rename = "type")]
    pub typ: IsmType,
}

#[cw_serde]
pub struct VerifyResponse {
    pub verified: bool,
}

#[cw_serde]
pub struct VerifyInfoResponse {
    pub threshold: u8,
    pub validators: Vec<HexBinary>,
}

#[cw_serde]
pub struct InterchainSecurityModuleResponse {
    pub ism: Option<Addr>,
}

pub fn recipient<C: CustomQuery>(
    querier: &QuerierWrapper<C>,
    recipient: impl Into<String>,
) -> StdResult<Option<Addr>> {
    let res = querier.query_wasm_smart::<InterchainSecurityModuleResponse>(
        recipient,
        &IsmSpecifierQueryMsg::InterchainSecurityModule().wrap(),
    )?;

    Ok(res.ism)
}

pub fn verify<C: CustomQuery>(
    querier: &QuerierWrapper<C>,
    ism: impl Into<String>,
    metadata: HexBinary,
    message: HexBinary,
) -> StdResult<bool> {
    let verify_resp = querier.query_wasm_smart::<VerifyResponse>(
        ism,
        &IsmQueryMsg::Verify { metadata, message }.wrap(),
    )?;

    Ok(verify_resp.verified)
}