ibc_client_cw/
handlers.rs1use core::fmt::Display;
2
3use cosmwasm_std::{to_json_binary, Binary};
4use ibc_core::client::context::prelude::*;
5use ibc_core::host::types::error::DecodingError;
6use ibc_core::host::types::path::ClientConsensusStatePath;
7use ibc_core::primitives::proto::Any;
8use prost::Message;
9
10use crate::api::ClientType;
11use crate::context::Context;
12use crate::types::{
13 CheckForMisbehaviourMsg, CheckForMisbehaviourResponse, ContractError, ContractResult,
14 InstantiateMsg, QueryMsg, StatusMsg, StatusResponse, SudoMsg, TimestampAtHeightResponse,
15 UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessageMsg,
16 VerifyClientMessageResponse, VerifyMembershipMsg, VerifyNonMembershipMsg,
17 VerifyUpgradeAndUpdateStateMsg,
18};
19
20impl<'a, C: ClientType<'a>> Context<'a, C>
21where
22 <C::ClientState as TryFrom<Any>>::Error: Display,
23 <C::ConsensusState as TryFrom<Any>>::Error: Display,
24{
25 pub fn instantiate(&mut self, msg: InstantiateMsg) -> Result<Binary, ContractError> {
27 let any = Any::decode(&mut msg.client_state.as_slice())?;
28
29 let client_state =
30 C::ClientState::try_from(any).map_err(DecodingError::invalid_raw_data)?;
31
32 let any_consensus_state = Any::decode(&mut msg.consensus_state.as_slice())?;
33
34 self.set_checksum(msg.checksum);
35
36 client_state.initialise(self, &self.client_id(), any_consensus_state)?;
37
38 Ok(to_json_binary(&ContractResult::success())?)
39 }
40
41 pub fn sudo(&mut self, msg: SudoMsg) -> Result<Binary, ContractError> {
43 let client_id = self.client_id();
44
45 if let SudoMsg::MigrateClientStore(_) = msg {
46 self.set_subject_prefix();
47 };
48
49 let client_state = self.client_state(&client_id)?;
50
51 let result = match msg {
52 SudoMsg::UpdateState(msg_raw) => {
53 let msg = UpdateStateMsg::try_from(msg_raw)?;
54
55 let heights = client_state.update_state(self, &client_id, msg.client_message)?;
56
57 ContractResult::success().heights(heights)
58 }
59 SudoMsg::UpdateStateOnMisbehaviour(msg_raw) => {
60 let msg = UpdateStateOnMisbehaviourMsg::try_from(msg_raw)?;
61
62 client_state.update_state_on_misbehaviour(self, &client_id, msg.client_message)?;
63
64 ContractResult::success()
65 }
66 SudoMsg::VerifyMembership(msg) => {
67 let msg = VerifyMembershipMsg::try_from(msg)?;
68
69 let client_cons_state_path = ClientConsensusStatePath::new(
70 self.client_id(),
71 msg.height.revision_number(),
72 msg.height.revision_height(),
73 );
74
75 let consensus_state = self.consensus_state(&client_cons_state_path)?;
76
77 client_state.verify_membership_raw(
78 &msg.prefix,
79 &msg.proof,
80 consensus_state.root(),
81 msg.path,
82 msg.value,
83 )?;
84
85 ContractResult::success()
86 }
87 SudoMsg::VerifyNonMembership(msg) => {
88 let msg = VerifyNonMembershipMsg::try_from(msg)?;
89
90 let client_cons_state_path = ClientConsensusStatePath::new(
91 client_id.clone(),
92 msg.height.revision_number(),
93 msg.height.revision_height(),
94 );
95
96 let consensus_state = self.consensus_state(&client_cons_state_path)?;
97
98 client_state.verify_non_membership_raw(
99 &msg.prefix,
100 &msg.proof,
101 consensus_state.root(),
102 msg.path,
103 )?;
104
105 ContractResult::success()
106 }
107 SudoMsg::VerifyUpgradeAndUpdateState(msg) => {
108 let msg = VerifyUpgradeAndUpdateStateMsg::try_from(msg)?;
109
110 let client_cons_state_path = ClientConsensusStatePath::new(
111 client_id.clone(),
112 client_state.latest_height().revision_number(),
113 client_state.latest_height().revision_height(),
114 );
115
116 let consensus_state = self.consensus_state(&client_cons_state_path)?;
117
118 client_state.verify_upgrade_client(
119 msg.upgrade_client_state.clone(),
120 msg.upgrade_consensus_state.clone(),
121 msg.proof_upgrade_client,
122 msg.proof_upgrade_consensus_state,
123 consensus_state.root(),
124 )?;
125
126 client_state.update_state_on_upgrade(
127 self,
128 &client_id,
129 msg.upgrade_client_state,
130 msg.upgrade_consensus_state,
131 )?;
132
133 ContractResult::success()
134 }
135 SudoMsg::MigrateClientStore(_) => {
136 self.set_substitute_prefix();
137 let substitute_client_state = self.client_state(&client_id)?;
138 let substitute_consensus_state =
139 self.consensus_state(&ClientConsensusStatePath::new(
140 client_id.clone(),
141 substitute_client_state.latest_height().revision_number(),
142 substitute_client_state.latest_height().revision_height(),
143 ))?;
144
145 let substitute_client_state_any = substitute_client_state.into();
146
147 self.set_subject_prefix();
148 client_state.check_substitute(self, substitute_client_state_any.clone())?;
149
150 client_state.update_on_recovery(
151 self,
152 &self.client_id(),
153 substitute_client_state_any,
154 substitute_consensus_state.into(),
155 )?;
156
157 ContractResult::success()
158 }
159 };
160 Ok(to_json_binary(&result)?)
161 }
162
163 pub fn query(&self, msg: QueryMsg) -> Result<Binary, ContractError> {
165 let client_id = self.client_id();
166
167 let client_state = self.client_state(&client_id)?;
168
169 match msg {
170 QueryMsg::Status(StatusMsg {}) => {
171 let status = client_state.status(self, &client_id)?;
172 to_json_binary(&StatusResponse { status })
173 }
174 QueryMsg::TimestampAtHeight(msg) => {
175 let client_cons_state_path = ClientConsensusStatePath::new(
176 client_id,
177 msg.height.revision_number(),
178 msg.height.revision_height(),
179 );
180
181 let consensus_state = self.consensus_state(&client_cons_state_path)?;
182 let timestamp = consensus_state.timestamp()?.nanoseconds();
183 to_json_binary(&TimestampAtHeightResponse { timestamp })
184 }
185 QueryMsg::VerifyClientMessage(msg) => {
186 let msg = VerifyClientMessageMsg::try_from(msg)?;
187
188 let is_valid = client_state
189 .verify_client_message(self, &client_id, msg.client_message)
190 .is_ok();
191 to_json_binary(&VerifyClientMessageResponse { is_valid })
192 }
193 QueryMsg::CheckForMisbehaviour(msg) => {
194 let msg = CheckForMisbehaviourMsg::try_from(msg)?;
195
196 let found_misbehaviour =
197 client_state.check_for_misbehaviour(self, &client_id, msg.client_message)?;
198 to_json_binary(&CheckForMisbehaviourResponse { found_misbehaviour })
199 }
200 }
201 .map_err(Into::into)
202 }
203}