penumbra_sdk_ibc/component/action_handler/
ibc_action.rs

1use std::sync::Arc;
2
3use anyhow::{ensure, Context, Result};
4use cnidarium::{StateRead, StateWrite};
5
6use crate::{
7    component::{app_handler::AppHandler, HostInterface, MsgHandler as _},
8    IbcRelay, IbcRelayWithHandlers, StateReadExt as _,
9};
10
11impl<AH: AppHandler, HI: HostInterface> IbcRelayWithHandlers<AH, HI> {
12    pub async fn check_stateless(&self, _context: ()) -> Result<()> {
13        let action = self.action();
14        match action {
15            IbcRelay::CreateClient(msg) => msg.check_stateless::<AH>().await?,
16            IbcRelay::UpdateClient(msg) => msg.check_stateless::<AH>().await?,
17            IbcRelay::UpgradeClient(msg) => msg.check_stateless::<AH>().await?,
18            IbcRelay::SubmitMisbehavior(msg) => msg.check_stateless::<AH>().await?,
19            IbcRelay::ConnectionOpenInit(msg) => msg.check_stateless::<AH>().await?,
20            IbcRelay::ConnectionOpenTry(msg) => msg.check_stateless::<AH>().await?,
21            IbcRelay::ConnectionOpenAck(msg) => msg.check_stateless::<AH>().await?,
22            IbcRelay::ConnectionOpenConfirm(msg) => msg.check_stateless::<AH>().await?,
23            IbcRelay::ChannelOpenInit(msg) => msg.check_stateless::<AH>().await?,
24            IbcRelay::ChannelOpenTry(msg) => msg.check_stateless::<AH>().await?,
25            IbcRelay::ChannelOpenAck(msg) => msg.check_stateless::<AH>().await?,
26            IbcRelay::ChannelOpenConfirm(msg) => msg.check_stateless::<AH>().await?,
27            IbcRelay::ChannelCloseInit(msg) => msg.check_stateless::<AH>().await?,
28            IbcRelay::ChannelCloseConfirm(msg) => msg.check_stateless::<AH>().await?,
29            IbcRelay::RecvPacket(msg) => msg.check_stateless::<AH>().await?,
30            IbcRelay::Acknowledgement(msg) => msg.check_stateless::<AH>().await?,
31            IbcRelay::Timeout(msg) => msg.check_stateless::<AH>().await?,
32            IbcRelay::Unknown(msg) => {
33                anyhow::bail!("unknown IBC message type: {}", msg.type_url)
34            }
35        }
36
37        Ok(())
38    }
39
40    pub async fn check_historical<S: StateRead + 'static>(&self, state: Arc<S>) -> Result<()> {
41        // SAFETY: this is safe to check here because ibc component parameters cannot change
42        // during transaction processing.
43        ensure!(
44            state.get_ibc_params().await?.ibc_enabled,
45            "transaction contains IBC actions, but IBC is not enabled"
46        );
47        Ok(())
48    }
49
50    pub async fn check_and_execute<S: StateWrite>(&self, state: S) -> Result<()> {
51        let action = self.action();
52        match action {
53            IbcRelay::CreateClient(msg) => msg
54                .try_execute::<S, AH, HI>(state)
55                .await
56                .context("failed to execute MsgCreateClient")?,
57            IbcRelay::UpdateClient(msg) => msg
58                .try_execute::<S, AH, HI>(state)
59                .await
60                .context("failed to execute MsgUpdateClient")?,
61            IbcRelay::UpgradeClient(msg) => msg
62                .try_execute::<S, AH, HI>(state)
63                .await
64                .context("failed to execute MsgUpgradeClient")?,
65            IbcRelay::SubmitMisbehavior(msg) => msg
66                .try_execute::<S, AH, HI>(state)
67                .await
68                .context("failed to execute MsgSubmitMisbehaviour")?,
69            IbcRelay::ConnectionOpenInit(msg) => msg
70                .try_execute::<S, AH, HI>(state)
71                .await
72                .context("failed to execute MsgConnectionOpenInit")?,
73            IbcRelay::ConnectionOpenTry(msg) => msg
74                .try_execute::<S, AH, HI>(state)
75                .await
76                .context("failed to execute MsgConnectionOpenTry")?,
77            IbcRelay::ConnectionOpenAck(msg) => msg
78                .try_execute::<S, AH, HI>(state)
79                .await
80                .context("failed to execute MsgConnectionOpenAck")?,
81            IbcRelay::ConnectionOpenConfirm(msg) => msg
82                .try_execute::<S, AH, HI>(state)
83                .await
84                .context("failed to execute MsgConnectionOpenConfirm")?,
85            IbcRelay::ChannelOpenInit(msg) => msg
86                .try_execute::<S, AH, HI>(state)
87                .await
88                .context("failed to execute MsgChannelOpenInit")?,
89            IbcRelay::ChannelOpenTry(msg) => msg
90                .try_execute::<S, AH, HI>(state)
91                .await
92                .context("failed to execute MsgChannelOpenTry")?,
93            IbcRelay::ChannelOpenAck(msg) => msg
94                .try_execute::<S, AH, HI>(state)
95                .await
96                .context("failed to execute MsgChannelOpenAck")?,
97            IbcRelay::ChannelOpenConfirm(msg) => msg
98                .try_execute::<S, AH, HI>(state)
99                .await
100                .context("failed to execute MsgChannelOpenConfirm")?,
101            IbcRelay::ChannelCloseInit(msg) => msg
102                .try_execute::<S, AH, HI>(state)
103                .await
104                .context("failed to execute MsgChannelCloseInit")?,
105            IbcRelay::ChannelCloseConfirm(msg) => msg
106                .try_execute::<S, AH, HI>(state)
107                .await
108                .context("failed to execute MsgChannelCloseConfirm")?,
109            IbcRelay::RecvPacket(msg) => msg
110                .try_execute::<S, AH, HI>(state)
111                .await
112                .context("failed to execute MsgRecvPacket")?,
113            IbcRelay::Acknowledgement(msg) => msg
114                .try_execute::<S, AH, HI>(state)
115                .await
116                .context("failed to execute MsgAcknowledgement")?,
117            IbcRelay::Timeout(msg) => msg
118                .try_execute::<S, AH, HI>(state)
119                .await
120                .context("failed to execute MsgTimeout")?,
121            IbcRelay::Unknown(msg) => {
122                anyhow::bail!("unknown IBC message type: {}", msg.type_url)
123            }
124        }
125
126        Ok(())
127    }
128}