1use ibc_proto::ibc::core::{
2 channel::v1::{
3 MsgAcknowledgement as RawMsgAcknowledgement,
4 MsgChannelCloseConfirm as RawMsgChannelCloseConfirm,
5 MsgChannelCloseInit as RawMsgChannelCloseInit, MsgChannelOpenAck as RawMsgChannelOpenAck,
6 MsgChannelOpenConfirm as RawMsgChannelOpenConfirm,
7 MsgChannelOpenInit as RawMsgChannelOpenInit, MsgChannelOpenTry as RawMsgChannelOpenTry,
8 MsgRecvPacket as RawMsgRecvPacket, MsgTimeout as RawMsgTimeout,
9 },
10 client::v1::{
11 MsgCreateClient as RawMsgCreateClient, MsgSubmitMisbehaviour as RawMsgSubmitMisbehaviour,
12 MsgUpdateClient as RawMsgUpdateClient, MsgUpgradeClient as RawMsgUpgradeClient,
13 },
14 connection::v1::{
15 MsgConnectionOpenAck as RawMsgConnectionOpenAck,
16 MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm,
17 MsgConnectionOpenInit as RawMsgConnectionOpenInit,
18 MsgConnectionOpenTry as RawMsgConnectionOpenTry,
19 },
20};
21use ibc_types::core::{
22 channel::msgs::{
23 MsgAcknowledgement, MsgChannelCloseConfirm, MsgChannelCloseInit, MsgChannelOpenAck,
24 MsgChannelOpenConfirm, MsgChannelOpenInit, MsgChannelOpenTry, MsgRecvPacket, MsgTimeout,
25 },
26 client::msgs::{MsgCreateClient, MsgSubmitMisbehaviour, MsgUpdateClient, MsgUpgradeClient},
27 connection::msgs::{
28 MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit, MsgConnectionOpenTry,
29 },
30};
31
32use ibc_types::DomainType as IbcTypesDomainType;
33
34use penumbra_sdk_proto::penumbra::core::component::ibc::v1::{self as pb};
35use penumbra_sdk_proto::{DomainType, Name};
36use penumbra_sdk_txhash::{EffectHash, EffectingData};
37use serde::{Deserialize, Serialize};
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(try_from = "pb::IbcRelay", into = "pb::IbcRelay")]
41pub enum IbcRelay {
42 CreateClient(MsgCreateClient),
43 UpdateClient(MsgUpdateClient),
44 UpgradeClient(MsgUpgradeClient),
45 SubmitMisbehavior(MsgSubmitMisbehaviour),
46 ConnectionOpenInit(MsgConnectionOpenInit),
47 ConnectionOpenTry(MsgConnectionOpenTry),
48 ConnectionOpenAck(MsgConnectionOpenAck),
49 ConnectionOpenConfirm(MsgConnectionOpenConfirm),
50 ChannelOpenInit(MsgChannelOpenInit),
51 ChannelOpenTry(MsgChannelOpenTry),
52 ChannelOpenAck(MsgChannelOpenAck),
53 ChannelOpenConfirm(MsgChannelOpenConfirm),
54 ChannelCloseInit(MsgChannelCloseInit),
55 ChannelCloseConfirm(MsgChannelCloseConfirm),
56 RecvPacket(MsgRecvPacket),
57 Acknowledgement(MsgAcknowledgement),
58 Timeout(MsgTimeout),
59 Unknown(pbjson_types::Any),
60}
61
62impl IbcRelay {
63 pub fn create_span(&self, parent: &tracing::Span) -> tracing::Span {
68 match self {
69 IbcRelay::CreateClient(msg) => {
70 match ibc_types::lightclients::tendermint::client_state::ClientState::try_from(
72 msg.client_state.clone(),
73 ) {
74 Ok(tm_client) => {
75 tracing::info_span!(parent: parent, "CreateClient", chain_id = %tm_client.chain_id)
76 }
77 Err(_) => tracing::info_span!(parent: parent, "CreateClient"),
78 }
79 }
80 IbcRelay::UpdateClient(msg) => {
81 tracing::info_span!(parent: parent, "UpdateClient", client_id = %msg.client_id)
82 }
83 IbcRelay::UpgradeClient(msg) => {
84 tracing::info_span!(parent: parent, "UpgradeClient", client_id = %msg.client_id)
85 }
86 IbcRelay::SubmitMisbehavior(msg) => {
87 tracing::info_span!(parent: parent, "SubmitMisbehavior", client_id = %msg.client_id)
88 }
89 IbcRelay::ConnectionOpenInit(msg) => {
90 tracing::info_span!(parent: parent, "ConnectionOpenInit", client_id = %msg.client_id_on_a)
91 }
92 IbcRelay::ConnectionOpenTry(msg) => {
93 tracing::info_span!(parent: parent, "ConnectionOpenTry", client_id = %msg.client_id_on_b)
94 }
95 IbcRelay::ConnectionOpenAck(msg) => {
96 tracing::info_span!(parent: parent, "ConnectionOpenAck", connection_id = %msg.conn_id_on_a)
97 }
98 IbcRelay::ConnectionOpenConfirm(msg) => {
99 tracing::info_span!(parent: parent, "ConnectionOpenConfirm", connection_id = %msg.conn_id_on_b)
100 }
101 IbcRelay::ChannelOpenInit(msg) => {
102 tracing::info_span!(parent: parent, "ChannelOpenInit", port_id = %msg.port_id_on_a)
103 }
104 IbcRelay::ChannelOpenTry(msg) => {
105 tracing::info_span!(parent: parent, "ChannelOpenTry", port_id = %msg.port_id_on_b)
106 }
107 IbcRelay::ChannelOpenAck(msg) => {
108 tracing::info_span!(parent: parent, "ChannelOpenAck", chan_id = %msg.chan_id_on_a)
109 }
110 IbcRelay::ChannelOpenConfirm(msg) => {
111 tracing::info_span!(parent: parent, "ChannelOpenConfirm", chan_id = %msg.chan_id_on_b)
112 }
113 IbcRelay::ChannelCloseInit(msg) => {
114 tracing::info_span!(parent: parent, "ChannelCloseInit", chan_id = %msg.chan_id_on_a)
115 }
116 IbcRelay::ChannelCloseConfirm(msg) => {
117 tracing::info_span!(parent: parent, "ChannelCloseConfirm", chan_id = %msg.chan_id_on_b)
118 }
119 IbcRelay::RecvPacket(msg) => {
120 tracing::info_span!(parent: parent, "RecvPacket", chan_id = %msg.packet.chan_on_b, seq = %msg.packet.sequence)
121 }
122 IbcRelay::Acknowledgement(msg) => {
123 tracing::info_span!(parent: parent, "Acknowledgement", chan_id = %msg.packet.chan_on_a, seq = %msg.packet.sequence)
124 }
125 IbcRelay::Timeout(msg) => {
126 tracing::info_span!(parent: parent, "Timeout", chan_id = %msg.packet.chan_on_a, seq = %msg.packet.sequence)
127 }
128 IbcRelay::Unknown(_) => {
129 tracing::info_span!(parent: parent, "Unknown")
130 }
131 }
132 }
133}
134
135impl EffectingData for IbcRelay {
136 fn effect_hash(&self) -> EffectHash {
137 EffectHash::from_proto_effecting_data(&self.to_proto())
138 }
139}
140
141impl DomainType for IbcRelay {
142 type Proto = pb::IbcRelay;
143}
144
145impl TryFrom<pb::IbcRelay> for IbcRelay {
146 type Error = anyhow::Error;
147 fn try_from(value: pb::IbcRelay) -> Result<Self, Self::Error> {
148 let raw_action = value
149 .raw_action
150 .ok_or_else(|| anyhow::anyhow!("empty IBC transaction is not allowed"))?;
151
152 let action_type = raw_action.type_url.as_str();
153 let raw_action_bytes = raw_action.value.clone();
154
155 let outer_msg = if action_type == RawMsgCreateClient::type_url() {
157 let msg = MsgCreateClient::decode(raw_action_bytes)?;
158 IbcRelay::CreateClient(msg)
159 } else if action_type == RawMsgUpdateClient::type_url() {
160 let msg = MsgUpdateClient::decode(raw_action_bytes)?;
161 IbcRelay::UpdateClient(msg)
162 } else if action_type == RawMsgUpgradeClient::type_url() {
163 let msg = MsgUpgradeClient::decode(raw_action_bytes)?;
164 IbcRelay::UpgradeClient(msg)
165 } else if action_type == RawMsgSubmitMisbehaviour::type_url() {
166 let msg = MsgSubmitMisbehaviour::decode(raw_action_bytes)?;
167 IbcRelay::SubmitMisbehavior(msg)
168 } else if action_type == RawMsgConnectionOpenInit::type_url() {
169 let msg = MsgConnectionOpenInit::decode(raw_action_bytes)?;
170 IbcRelay::ConnectionOpenInit(msg)
171 } else if action_type == RawMsgConnectionOpenTry::type_url() {
172 let msg = MsgConnectionOpenTry::decode(raw_action_bytes)?;
173 IbcRelay::ConnectionOpenTry(msg)
174 } else if action_type == RawMsgConnectionOpenAck::type_url() {
175 let msg = MsgConnectionOpenAck::decode(raw_action_bytes)?;
176 IbcRelay::ConnectionOpenAck(msg)
177 } else if action_type == RawMsgConnectionOpenConfirm::type_url() {
178 let msg = MsgConnectionOpenConfirm::decode(raw_action_bytes)?;
179 IbcRelay::ConnectionOpenConfirm(msg)
180 } else if action_type == RawMsgAcknowledgement::type_url() {
181 let msg = MsgAcknowledgement::decode(raw_action_bytes)?;
182 IbcRelay::Acknowledgement(msg)
183 } else if action_type == RawMsgChannelOpenInit::type_url() {
184 let msg = MsgChannelOpenInit::decode(raw_action_bytes)?;
185 IbcRelay::ChannelOpenInit(msg)
186 } else if action_type == RawMsgChannelOpenTry::type_url() {
187 let msg = MsgChannelOpenTry::decode(raw_action_bytes)?;
188 IbcRelay::ChannelOpenTry(msg)
189 } else if action_type == RawMsgChannelOpenAck::type_url() {
190 let msg = MsgChannelOpenAck::decode(raw_action_bytes)?;
191 IbcRelay::ChannelOpenAck(msg)
192 } else if action_type == RawMsgChannelOpenConfirm::type_url() {
193 let msg = MsgChannelOpenConfirm::decode(raw_action_bytes)?;
194 IbcRelay::ChannelOpenConfirm(msg)
195 } else if action_type == RawMsgChannelCloseInit::type_url() {
196 let msg = MsgChannelCloseInit::decode(raw_action_bytes)?;
197 IbcRelay::ChannelCloseInit(msg)
198 } else if action_type == RawMsgChannelCloseConfirm::type_url() {
199 let msg = MsgChannelCloseConfirm::decode(raw_action_bytes)?;
200 IbcRelay::ChannelCloseConfirm(msg)
201 } else if action_type == RawMsgRecvPacket::type_url() {
202 let msg = MsgRecvPacket::decode(raw_action_bytes)?;
203 IbcRelay::RecvPacket(msg)
204 } else if action_type == RawMsgTimeout::type_url() {
205 let msg = MsgTimeout::decode(raw_action_bytes)?;
206 IbcRelay::Timeout(msg)
207 } else {
208 IbcRelay::Unknown(raw_action)
209 };
210
211 Ok(outer_msg)
212 }
213}
214
215impl From<IbcRelay> for pb::IbcRelay {
216 fn from(value: IbcRelay) -> Self {
217 let raw_action = match value {
218 IbcRelay::CreateClient(msg) => pbjson_types::Any {
219 type_url: RawMsgCreateClient::type_url(),
220 value: msg.encode_to_vec().into(),
221 },
222 IbcRelay::UpdateClient(msg) => pbjson_types::Any {
223 type_url: RawMsgUpdateClient::type_url(),
224 value: msg.encode_to_vec().into(),
225 },
226 IbcRelay::UpgradeClient(msg) => pbjson_types::Any {
227 type_url: RawMsgUpgradeClient::type_url(),
228 value: msg.encode_to_vec().into(),
229 },
230 IbcRelay::SubmitMisbehavior(msg) => pbjson_types::Any {
231 type_url: RawMsgSubmitMisbehaviour::type_url(),
232 value: msg.encode_to_vec().into(),
233 },
234 IbcRelay::ConnectionOpenInit(msg) => pbjson_types::Any {
235 type_url: RawMsgConnectionOpenInit::type_url(),
236 value: msg.encode_to_vec().into(),
237 },
238 IbcRelay::ConnectionOpenTry(msg) => pbjson_types::Any {
239 type_url: RawMsgConnectionOpenTry::type_url(),
240 value: msg.encode_to_vec().into(),
241 },
242 IbcRelay::ConnectionOpenAck(msg) => pbjson_types::Any {
243 type_url: RawMsgConnectionOpenAck::type_url(),
244 value: msg.encode_to_vec().into(),
245 },
246 IbcRelay::ConnectionOpenConfirm(msg) => pbjson_types::Any {
247 type_url: RawMsgConnectionOpenConfirm::type_url(),
248 value: msg.encode_to_vec().into(),
249 },
250 IbcRelay::Acknowledgement(msg) => pbjson_types::Any {
251 type_url: RawMsgAcknowledgement::type_url(),
252 value: msg.encode_to_vec().into(),
253 },
254 IbcRelay::ChannelOpenInit(msg) => pbjson_types::Any {
255 type_url: RawMsgChannelOpenInit::type_url(),
256 value: msg.encode_to_vec().into(),
257 },
258 IbcRelay::ChannelOpenTry(msg) => pbjson_types::Any {
259 type_url: RawMsgChannelOpenTry::type_url(),
260 value: msg.encode_to_vec().into(),
261 },
262 IbcRelay::ChannelOpenAck(msg) => pbjson_types::Any {
263 type_url: RawMsgChannelOpenAck::type_url(),
264 value: msg.encode_to_vec().into(),
265 },
266 IbcRelay::ChannelOpenConfirm(msg) => pbjson_types::Any {
267 type_url: RawMsgChannelOpenConfirm::type_url(),
268 value: msg.encode_to_vec().into(),
269 },
270 IbcRelay::ChannelCloseInit(msg) => pbjson_types::Any {
271 type_url: RawMsgChannelCloseInit::type_url(),
272 value: msg.encode_to_vec().into(),
273 },
274 IbcRelay::ChannelCloseConfirm(msg) => pbjson_types::Any {
275 type_url: RawMsgChannelCloseConfirm::type_url(),
276 value: msg.encode_to_vec().into(),
277 },
278 IbcRelay::RecvPacket(msg) => pbjson_types::Any {
279 type_url: RawMsgRecvPacket::type_url(),
280 value: msg.encode_to_vec().into(),
281 },
282 IbcRelay::Timeout(msg) => pbjson_types::Any {
283 type_url: RawMsgTimeout::type_url(),
284 value: msg.encode_to_vec().into(),
285 },
286 IbcRelay::Unknown(raw_action) => raw_action,
287 };
288 pb::IbcRelay {
289 raw_action: Some(raw_action),
290 }
291 }
292}