ibc_core_client/handler/
update_client.rs1use ibc_core_client_context::prelude::*;
4use ibc_core_client_types::error::ClientError;
5use ibc_core_client_types::events::{ClientMisbehaviour, UpdateClient};
6use ibc_core_client_types::msgs::MsgUpdateOrMisbehaviour;
7use ibc_core_client_types::UpdateKind;
8use ibc_core_handler_types::events::{IbcEvent, MessageEvent};
9use ibc_core_host::types::error::HostError;
10use ibc_core_host::{ExecutionContext, ValidationContext};
11use ibc_primitives::prelude::*;
12use ibc_primitives::ToVec;
13
14pub fn validate<Ctx>(ctx: &Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), ClientError>
15where
16 Ctx: ValidationContext,
17{
18 ctx.validate_message_signer(msg.signer())?;
19
20 let client_id = msg.client_id().clone();
21
22 let client_val_ctx = ctx.get_client_validation_context();
23
24 let client_state = client_val_ctx.client_state(&client_id)?;
26
27 client_state
28 .status(client_val_ctx, &client_id)?
29 .verify_is_active()?;
30
31 let client_message = msg.client_message();
32
33 client_state.verify_client_message(client_val_ctx, &client_id, client_message)?;
34
35 Ok(())
36}
37
38pub fn execute<Ctx>(ctx: &mut Ctx, msg: MsgUpdateOrMisbehaviour) -> Result<(), ClientError>
39where
40 Ctx: ExecutionContext,
41{
42 let client_id = msg.client_id().clone();
43 let update_kind = match msg {
44 MsgUpdateOrMisbehaviour::UpdateClient(_) => UpdateKind::UpdateClient,
45 MsgUpdateOrMisbehaviour::Misbehaviour(_) => UpdateKind::SubmitMisbehaviour,
46 };
47 let client_message = msg.client_message();
48
49 let client_exec_ctx = ctx.get_client_execution_context();
50
51 let client_state = client_exec_ctx.client_state(&client_id)?;
52
53 let found_misbehaviour =
54 client_state.check_for_misbehaviour(client_exec_ctx, &client_id, client_message.clone())?;
55
56 if found_misbehaviour {
57 client_state.update_state_on_misbehaviour(client_exec_ctx, &client_id, client_message)?;
58
59 let event = IbcEvent::ClientMisbehaviour(ClientMisbehaviour::new(
60 client_id,
61 client_state.client_type(),
62 ));
63 ctx.emit_ibc_event(IbcEvent::Message(MessageEvent::Client))?;
64 ctx.emit_ibc_event(event)?;
65 } else {
66 if !matches!(update_kind, UpdateKind::UpdateClient) {
67 return Err(ClientError::FailedToHandleMisbehaviour {
68 description: "misbehaviour submitted, but none found".to_string(),
69 });
70 }
71
72 let header = client_message;
73
74 let consensus_heights =
75 client_state.update_state(client_exec_ctx, &client_id, header.clone())?;
76
77 {
78 let event = {
79 let consensus_height = consensus_heights.first().ok_or(
80 HostError::missing_state("updated height in client update state"),
81 )?;
82
83 IbcEvent::UpdateClient(UpdateClient::new(
84 client_id,
85 client_state.client_type(),
86 *consensus_height,
87 consensus_heights,
88 header.to_vec(),
89 ))
90 };
91 ctx.emit_ibc_event(IbcEvent::Message(MessageEvent::Client))?;
92 ctx.emit_ibc_event(event)?;
93 }
94 }
95
96 Ok(())
97}