ibc_core_client/handler/
recover_client.rs1use ibc_core_client_context::prelude::*;
4use ibc_core_client_types::error::ClientError;
5use ibc_core_client_types::msgs::MsgRecoverClient;
6use ibc_core_host::types::path::ClientConsensusStatePath;
7use ibc_core_host::{ExecutionContext, ValidationContext};
8
9pub fn validate<Ctx>(ctx: &Ctx, msg: MsgRecoverClient) -> Result<(), ClientError>
14where
15 Ctx: ValidationContext,
16{
17 let signer = msg.signer;
18 let subject_client_id = msg.subject_client_id.clone();
19 let substitute_client_id = msg.substitute_client_id.clone();
20
21 ctx.validate_message_signer(&signer)?;
22
23 let client_val_ctx = ctx.get_client_validation_context();
24
25 let subject_client_state = client_val_ctx.client_state(&subject_client_id)?;
26 let substitute_client_state = client_val_ctx.client_state(&substitute_client_id)?;
27
28 let subject_height = subject_client_state.latest_height();
29 let substitute_height = substitute_client_state.latest_height();
30
31 if subject_height >= substitute_height {
32 return Err(ClientError::InvalidClientRecoveryHeights {
33 subject_height,
34 substitute_height,
35 });
36 }
37
38 substitute_client_state
39 .status(ctx.get_client_validation_context(), &substitute_client_id)?
40 .verify_is_active()?;
41
42 subject_client_state
44 .status(ctx.get_client_validation_context(), &subject_client_id)?
45 .verify_is_inactive()?;
46
47 subject_client_state.check_substitute(
51 ctx.get_client_validation_context(),
52 substitute_client_state.into(),
53 )?;
54
55 Ok(())
56}
57
58pub fn execute<Ctx>(ctx: &mut Ctx, msg: MsgRecoverClient) -> Result<(), ClientError>
64where
65 Ctx: ExecutionContext,
66{
67 let subject_client_id = msg.subject_client_id.clone();
68 let substitute_client_id = msg.substitute_client_id.clone();
69
70 let client_exec_ctx = ctx.get_client_execution_context();
71
72 let subject_client_state = client_exec_ctx.client_state(&subject_client_id)?;
73 let substitute_client_state = client_exec_ctx.client_state(&substitute_client_id)?;
74 let substitute_consensus_state =
75 client_exec_ctx.consensus_state(&ClientConsensusStatePath::new(
76 substitute_client_id.clone(),
77 substitute_client_state.latest_height().revision_number(),
78 substitute_client_state.latest_height().revision_height(),
79 ))?;
80
81 subject_client_state.update_on_recovery(
82 ctx.get_client_execution_context(),
83 &subject_client_id,
84 substitute_client_state.into(),
85 substitute_consensus_state.into(),
86 )?;
87
88 Ok(())
89}