1use ibc_core_channel::handler::{
2 acknowledgement_packet_execute, acknowledgement_packet_validate, chan_close_confirm_execute,
3 chan_close_confirm_validate, chan_close_init_execute, chan_close_init_validate,
4 chan_open_ack_execute, chan_open_ack_validate, chan_open_confirm_execute,
5 chan_open_confirm_validate, chan_open_init_execute, chan_open_init_validate,
6 chan_open_try_execute, chan_open_try_validate, recv_packet_execute, recv_packet_validate,
7 timeout_packet_execute, timeout_packet_validate, TimeoutMsgType,
8};
9use ibc_core_channel::types::msgs::{
10 channel_msg_to_port_id, packet_msg_to_port_id, ChannelMsg, PacketMsg,
11};
12use ibc_core_client::context::{ClientExecutionContext, ClientValidationContext};
13use ibc_core_client::handler::{create_client, update_client, upgrade_client};
14use ibc_core_client::types::error::ClientError;
15use ibc_core_client::types::msgs::{ClientMsg, MsgUpdateOrMisbehaviour};
16use ibc_core_connection::handler::{
17 conn_open_ack, conn_open_confirm, conn_open_init, conn_open_try,
18};
19use ibc_core_connection::types::msgs::ConnectionMsg;
20use ibc_core_handler_types::error::HandlerError;
21use ibc_core_handler_types::msgs::MsgEnvelope;
22use ibc_core_host::types::error::HostError;
23use ibc_core_host::{ExecutionContext, ValidationContext};
24use ibc_core_router::router::Router;
25use ibc_core_router::types::error::RouterError;
26use ibc_primitives::prelude::*;
27use ibc_primitives::proto::Any;
28
29pub fn dispatch<Ctx>(
31 ctx: &mut Ctx,
32 router: &mut impl Router,
33 msg: MsgEnvelope,
34) -> Result<(), HandlerError>
35where
36 Ctx: ExecutionContext,
37 <<Ctx::V as ClientValidationContext>::ClientStateRef as TryFrom<Any>>::Error: Into<ClientError>,
38 <<Ctx::E as ClientExecutionContext>::ClientStateMut as TryFrom<Any>>::Error: Into<ClientError>,
39 <Ctx::HostClientState as TryFrom<Any>>::Error: Into<ClientError>,
40{
41 validate(ctx, router, msg.clone())?;
42 execute(ctx, router, msg)
43}
44
45pub fn validate<Ctx>(ctx: &Ctx, router: &impl Router, msg: MsgEnvelope) -> Result<(), HandlerError>
54where
55 Ctx: ValidationContext,
56 <<Ctx::V as ClientValidationContext>::ClientStateRef as TryFrom<Any>>::Error: Into<ClientError>,
57 <Ctx::HostClientState as TryFrom<Any>>::Error: Into<ClientError>,
58{
59 match msg {
60 MsgEnvelope::Client(msg) => match msg {
61 ClientMsg::CreateClient(msg) => create_client::validate(ctx, msg)?,
62 ClientMsg::UpdateClient(msg) => {
63 update_client::validate(ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg))?
64 }
65 ClientMsg::Misbehaviour(msg) => {
66 update_client::validate(ctx, MsgUpdateOrMisbehaviour::Misbehaviour(msg))?
67 }
68 ClientMsg::UpgradeClient(msg) => upgrade_client::validate(ctx, msg)?,
69 ClientMsg::RecoverClient(_msg) => {
70 }
73 },
74 MsgEnvelope::Connection(msg) => match msg {
75 ConnectionMsg::OpenInit(msg) => conn_open_init::validate(ctx, msg)?,
76 ConnectionMsg::OpenTry(msg) => conn_open_try::validate(ctx, msg)?,
77 ConnectionMsg::OpenAck(msg) => conn_open_ack::validate(ctx, msg)?,
78 ConnectionMsg::OpenConfirm(msg) => conn_open_confirm::validate(ctx, &msg)?,
79 },
80 MsgEnvelope::Channel(msg) => {
81 let port_id = channel_msg_to_port_id(&msg);
82 let module_id = router.lookup_module(port_id).ok_or(RouterError::Host(
83 HostError::missing_state(format!("missing module ID for port {}", port_id.clone())),
84 ))?;
85 let module = router
86 .get_route(&module_id)
87 .ok_or(RouterError::MissingModule)?;
88
89 match msg {
90 ChannelMsg::OpenInit(msg) => chan_open_init_validate(ctx, module, msg)?,
91 ChannelMsg::OpenTry(msg) => chan_open_try_validate(ctx, module, msg)?,
92 ChannelMsg::OpenAck(msg) => chan_open_ack_validate(ctx, module, msg)?,
93 ChannelMsg::OpenConfirm(msg) => chan_open_confirm_validate(ctx, module, msg)?,
94 ChannelMsg::CloseInit(msg) => chan_close_init_validate(ctx, module, msg)?,
95 ChannelMsg::CloseConfirm(msg) => chan_close_confirm_validate(ctx, module, msg)?,
96 }
97 }
98 MsgEnvelope::Packet(msg) => {
99 let port_id = packet_msg_to_port_id(&msg);
100 let module_id = router.lookup_module(port_id).ok_or(RouterError::Host(
101 HostError::missing_state(format!("missing module ID for port {}", port_id.clone())),
102 ))?;
103 let module = router
104 .get_route(&module_id)
105 .ok_or(RouterError::MissingModule)?;
106
107 match msg {
108 PacketMsg::Recv(msg) => recv_packet_validate(ctx, msg)?,
109 PacketMsg::Ack(msg) => acknowledgement_packet_validate(ctx, module, msg)?,
110 PacketMsg::Timeout(msg) => {
111 timeout_packet_validate(ctx, module, TimeoutMsgType::Timeout(msg))?
112 }
113 PacketMsg::TimeoutOnClose(msg) => {
114 timeout_packet_validate(ctx, module, TimeoutMsgType::TimeoutOnClose(msg))?
115 }
116 }
117 }
118 };
119
120 Ok(())
121}
122
123pub fn execute<Ctx>(
125 ctx: &mut Ctx,
126 router: &mut impl Router,
127 msg: MsgEnvelope,
128) -> Result<(), HandlerError>
129where
130 Ctx: ExecutionContext,
131 <<Ctx::E as ClientExecutionContext>::ClientStateMut as TryFrom<Any>>::Error: Into<ClientError>,
132{
133 match msg {
134 MsgEnvelope::Client(msg) => match msg {
135 ClientMsg::CreateClient(msg) => create_client::execute(ctx, msg)?,
136 ClientMsg::UpdateClient(msg) => {
137 update_client::execute(ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg))?
138 }
139 ClientMsg::Misbehaviour(msg) => {
140 update_client::execute(ctx, MsgUpdateOrMisbehaviour::Misbehaviour(msg))?
141 }
142 ClientMsg::UpgradeClient(msg) => upgrade_client::execute(ctx, msg)?,
143 ClientMsg::RecoverClient(_msg) => {
144 }
147 },
148 MsgEnvelope::Connection(msg) => match msg {
149 ConnectionMsg::OpenInit(msg) => conn_open_init::execute(ctx, msg)?,
150 ConnectionMsg::OpenTry(msg) => conn_open_try::execute(ctx, msg)?,
151 ConnectionMsg::OpenAck(msg) => conn_open_ack::execute(ctx, msg)?,
152 ConnectionMsg::OpenConfirm(msg) => conn_open_confirm::execute(ctx, &msg)?,
153 },
154 MsgEnvelope::Channel(msg) => {
155 let port_id = channel_msg_to_port_id(&msg);
156 let module_id = router.lookup_module(port_id).ok_or(RouterError::Host(
157 HostError::missing_state(format!("missing module ID for port {}", port_id.clone())),
158 ))?;
159 let module = router
160 .get_route_mut(&module_id)
161 .ok_or(RouterError::MissingModule)?;
162
163 match msg {
164 ChannelMsg::OpenInit(msg) => chan_open_init_execute(ctx, module, msg)?,
165 ChannelMsg::OpenTry(msg) => chan_open_try_execute(ctx, module, msg)?,
166 ChannelMsg::OpenAck(msg) => chan_open_ack_execute(ctx, module, msg)?,
167 ChannelMsg::OpenConfirm(msg) => chan_open_confirm_execute(ctx, module, msg)?,
168 ChannelMsg::CloseInit(msg) => chan_close_init_execute(ctx, module, msg)?,
169 ChannelMsg::CloseConfirm(msg) => chan_close_confirm_execute(ctx, module, msg)?,
170 }
171 }
172 MsgEnvelope::Packet(msg) => {
173 let port_id = packet_msg_to_port_id(&msg);
174 let module_id = router.lookup_module(port_id).ok_or(RouterError::Host(
175 HostError::missing_state(format!("missing module ID for port {}", port_id.clone())),
176 ))?;
177 let module = router
178 .get_route_mut(&module_id)
179 .ok_or(RouterError::MissingModule)?;
180
181 match msg {
182 PacketMsg::Recv(msg) => recv_packet_execute(ctx, module, msg)?,
183 PacketMsg::Ack(msg) => acknowledgement_packet_execute(ctx, module, msg)?,
184 PacketMsg::Timeout(msg) => {
185 timeout_packet_execute(ctx, module, TimeoutMsgType::Timeout(msg))?
186 }
187 PacketMsg::TimeoutOnClose(msg) => {
188 timeout_packet_execute(ctx, module, TimeoutMsgType::TimeoutOnClose(msg))?
189 }
190 }
191 }
192 }
193
194 Ok(())
195}