use ibc_core_client_context::client_state::{
ClientStateCommon, ClientStateExecution, ClientStateValidation,
};
use ibc_core_client_context::consensus_state::ConsensusState;
use ibc_core_client_types::error::ClientError;
use ibc_core_client_types::events::UpgradeClient;
use ibc_core_client_types::msgs::MsgUpgradeClient;
use ibc_core_handler_types::error::ContextError;
use ibc_core_handler_types::events::{IbcEvent, MessageEvent};
use ibc_core_host::types::path::ClientConsensusStatePath;
use ibc_core_host::{ExecutionContext, ValidationContext};
use ibc_primitives::prelude::*;
pub fn validate<Ctx>(ctx: &Ctx, msg: MsgUpgradeClient) -> Result<(), ContextError>
where
Ctx: ValidationContext,
{
let MsgUpgradeClient {
client_id, signer, ..
} = msg;
ctx.validate_message_signer(&signer)?;
let old_client_state = ctx.client_state(&client_id)?;
old_client_state
.status(ctx.get_client_validation_context(), &client_id)?
.verify_is_active()?;
let old_client_cons_state_path = ClientConsensusStatePath::new(
client_id.clone(),
old_client_state.latest_height().revision_number(),
old_client_state.latest_height().revision_height(),
);
let old_consensus_state = ctx
.consensus_state(&old_client_cons_state_path)
.map_err(|_| ClientError::ConsensusStateNotFound {
client_id,
height: old_client_state.latest_height(),
})?;
old_client_state.verify_upgrade_client(
msg.upgraded_client_state.clone(),
msg.upgraded_consensus_state,
msg.proof_upgrade_client,
msg.proof_upgrade_consensus_state,
old_consensus_state.root(),
)?;
Ok(())
}
pub fn execute<Ctx>(ctx: &mut Ctx, msg: MsgUpgradeClient) -> Result<(), ContextError>
where
Ctx: ExecutionContext,
{
let MsgUpgradeClient { client_id, .. } = msg;
let old_client_state = ctx.client_state(&client_id)?;
let latest_height = old_client_state.update_state_on_upgrade(
ctx.get_client_execution_context(),
&client_id,
msg.upgraded_client_state.clone(),
msg.upgraded_consensus_state,
)?;
let event = IbcEvent::UpgradeClient(UpgradeClient::new(
client_id,
old_client_state.client_type(),
latest_height,
));
ctx.emit_ibc_event(IbcEvent::Message(MessageEvent::Client))?;
ctx.emit_ibc_event(event)?;
Ok(())
}