penumbra_ibc/component/action_handler/
ibc_action.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::sync::Arc;

use anyhow::{ensure, Context, Result};
use cnidarium::{StateRead, StateWrite};

use crate::{
    component::{app_handler::AppHandler, HostInterface, MsgHandler as _},
    IbcRelay, IbcRelayWithHandlers, StateReadExt as _,
};

impl<AH: AppHandler, HI: HostInterface> IbcRelayWithHandlers<AH, HI> {
    pub async fn check_stateless(&self, _context: ()) -> Result<()> {
        let action = self.action();
        match action {
            IbcRelay::CreateClient(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::UpdateClient(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::UpgradeClient(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::SubmitMisbehavior(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ConnectionOpenInit(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ConnectionOpenTry(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ConnectionOpenAck(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ConnectionOpenConfirm(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ChannelOpenInit(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ChannelOpenTry(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ChannelOpenAck(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ChannelOpenConfirm(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ChannelCloseInit(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::ChannelCloseConfirm(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::RecvPacket(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::Acknowledgement(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::Timeout(msg) => msg.check_stateless::<AH>().await?,
            IbcRelay::Unknown(msg) => {
                anyhow::bail!("unknown IBC message type: {}", msg.type_url)
            }
        }

        Ok(())
    }

    pub async fn check_historical<S: StateRead + 'static>(&self, state: Arc<S>) -> Result<()> {
        // SAFETY: this is safe to check here because ibc component parameters cannot change
        // during transaction processing.
        ensure!(
            state.get_ibc_params().await?.ibc_enabled,
            "transaction contains IBC actions, but IBC is not enabled"
        );
        Ok(())
    }

    pub async fn check_and_execute<S: StateWrite>(&self, state: S) -> Result<()> {
        let action = self.action();
        match action {
            IbcRelay::CreateClient(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgCreateClient")?,
            IbcRelay::UpdateClient(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgUpdateClient")?,
            IbcRelay::UpgradeClient(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgUpgradeClient")?,
            IbcRelay::SubmitMisbehavior(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgSubmitMisbehaviour")?,
            IbcRelay::ConnectionOpenInit(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgConnectionOpenInit")?,
            IbcRelay::ConnectionOpenTry(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgConnectionOpenTry")?,
            IbcRelay::ConnectionOpenAck(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgConnectionOpenAck")?,
            IbcRelay::ConnectionOpenConfirm(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgConnectionOpenConfirm")?,
            IbcRelay::ChannelOpenInit(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgChannelOpenInit")?,
            IbcRelay::ChannelOpenTry(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgChannelOpenTry")?,
            IbcRelay::ChannelOpenAck(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgChannelOpenAck")?,
            IbcRelay::ChannelOpenConfirm(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgChannelOpenConfirm")?,
            IbcRelay::ChannelCloseInit(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgChannelCloseInit")?,
            IbcRelay::ChannelCloseConfirm(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgChannelCloseConfirm")?,
            IbcRelay::RecvPacket(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgRecvPacket")?,
            IbcRelay::Acknowledgement(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgAcknowledgement")?,
            IbcRelay::Timeout(msg) => msg
                .try_execute::<S, AH, HI>(state)
                .await
                .context("failed to execute MsgTimeout")?,
            IbcRelay::Unknown(msg) => {
                anyhow::bail!("unknown IBC message type: {}", msg.type_url)
            }
        }

        Ok(())
    }
}