penumbra_sdk_ibc/component/msg_handler/
create_client.rs1use anyhow::{Context, Result};
2use async_trait::async_trait;
3use cnidarium::StateWrite;
4use ibc_types::{
5 core::client::{events::CreateClient, msgs::MsgCreateClient, ClientId},
6 lightclients::tendermint::client_type,
7};
8
9use crate::component::{
10 client::{ConsensusStateWriteExt as _, StateReadExt as _, StateWriteExt as _},
11 client_counter::ClientCounter,
12 ics02_validation, HostInterface, MsgHandler,
13};
14
15#[async_trait]
16impl MsgHandler for MsgCreateClient {
17 async fn check_stateless<H>(&self) -> Result<()> {
18 client_state_is_tendermint(self)?;
19 consensus_state_is_tendermint(self)?;
20
21 Ok(())
22 }
23
24 async fn try_execute<S: StateWrite, AH, HI: HostInterface>(&self, mut state: S) -> Result<()> {
32 tracing::debug!(msg = ?self);
33 let client_state =
34 ics02_validation::get_tendermint_client_state(self.client_state.clone())?;
35
36 let id_counter = state.client_counter().await?;
38 let client_id = ClientId::new(client_type(), id_counter.0)?;
39
40 tracing::info!("creating client {:?}", client_id);
41
42 let consensus_state =
43 ics02_validation::get_tendermint_consensus_state(self.consensus_state.clone())?;
44
45 state.put_client(&client_id, client_state.clone());
47
48 state
50 .put_verified_consensus_state::<HI>(
51 client_state.latest_height(),
52 client_id.clone(),
53 consensus_state,
54 )
55 .await
56 .context("unable to put verified consensus state")?;
57
58 let counter = state.client_counter().await.unwrap_or(ClientCounter(0));
60 state.put_client_counter(ClientCounter(counter.0 + 1));
61
62 state.record(
63 CreateClient {
64 client_id: client_id.clone(),
65 client_type: client_type(),
66 consensus_height: client_state.latest_height(),
67 }
68 .into(),
69 );
70 Ok(())
71 }
72}
73fn client_state_is_tendermint(msg: &MsgCreateClient) -> anyhow::Result<()> {
74 if ics02_validation::is_tendermint_client_state(&msg.client_state) {
75 Ok(())
76 } else {
77 Err(anyhow::anyhow!(
78 "MsgCreateClient: not a tendermint client state"
79 ))
80 }
81}
82
83fn consensus_state_is_tendermint(msg: &MsgCreateClient) -> anyhow::Result<()> {
84 if ics02_validation::is_tendermint_consensus_state(&msg.consensus_state) {
85 Ok(())
86 } else {
87 Err(anyhow::anyhow!(
88 "MsgCreateClient: not a tendermint consensus state"
89 ))
90 }
91}