ibc_core_channel/handler/
acknowledgement.rs1use ibc_core_channel_types::acknowledgement::Acknowledgement;
2use ibc_core_channel_types::channel::{ChannelEnd, Counterparty, Order, State as ChannelState};
3use ibc_core_channel_types::commitment::{compute_ack_commitment, compute_packet_commitment};
4use ibc_core_channel_types::error::ChannelError;
5use ibc_core_channel_types::events::{AcknowledgePacket, WriteAcknowledgement};
6use ibc_core_channel_types::msgs::MsgAcknowledgement;
7use ibc_core_channel_types::packet::{Packet, Receipt};
8use ibc_core_client::context::prelude::*;
9use ibc_core_connection::delay::verify_conn_delay_passed;
10use ibc_core_connection::types::State as ConnectionState;
11use ibc_core_handler_types::events::{IbcEvent, MessageEvent};
12use ibc_core_host::types::path::{
13 AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, Path, ReceiptPath,
14 SeqAckPath, SeqRecvPath,
15};
16use ibc_core_host::{ExecutionContext, ValidationContext};
17use ibc_core_router::module::Module;
18use ibc_primitives::prelude::*;
19
20pub fn commit_packet_sequence_number_with_chan_end<ExecCtx>(
21 ctx_b: &mut ExecCtx,
22 chan_end_on_b: &ChannelEnd,
23 packet: &Packet,
24) -> Result<(), ChannelError>
25where
26 ExecCtx: ExecutionContext,
27{
28 match chan_end_on_b.ordering {
30 Order::Unordered => {
31 let receipt_path_on_b = ReceiptPath {
32 port_id: packet.port_id_on_b.clone(),
33 channel_id: packet.chan_id_on_b.clone(),
34 sequence: packet.seq_on_a,
35 };
36
37 ctx_b.store_packet_receipt(&receipt_path_on_b, Receipt::Ok)?;
38 }
39 Order::Ordered => {
40 let seq_recv_path_on_b = SeqRecvPath::new(&packet.port_id_on_b, &packet.chan_id_on_b);
41 let next_seq_recv = ctx_b.get_next_sequence_recv(&seq_recv_path_on_b)?;
42 ctx_b.store_next_sequence_recv(&seq_recv_path_on_b, next_seq_recv.increment())?;
43 }
44 _ => {}
45 }
46
47 Ok(())
48}
49
50pub fn commit_packet_sequence_number<ExecCtx>(
51 ctx_b: &mut ExecCtx,
52 packet: &Packet,
53) -> Result<(), ChannelError>
54where
55 ExecCtx: ExecutionContext,
56{
57 let chan_end_path_on_b = ChannelEndPath::new(&packet.port_id_on_b, &packet.chan_id_on_b);
58 let chan_end_on_b = ctx_b.channel_end(&chan_end_path_on_b)?;
59
60 commit_packet_sequence_number_with_chan_end(ctx_b, &chan_end_on_b, packet)
61}
62
63pub fn commit_packet_acknowledgment<ExecCtx>(
64 ctx_b: &mut ExecCtx,
65 packet: &Packet,
66 acknowledgement: &Acknowledgement,
67) -> Result<(), ChannelError>
68where
69 ExecCtx: ExecutionContext,
70{
71 let ack_path_on_b = AckPath::new(&packet.port_id_on_b, &packet.chan_id_on_b, packet.seq_on_a);
72
73 ctx_b.store_packet_acknowledgement(&ack_path_on_b, compute_ack_commitment(acknowledgement))?;
75
76 Ok(())
77}
78
79pub fn emit_packet_acknowledgement_event_with_chan_end<ExecCtx>(
80 ctx_b: &mut ExecCtx,
81 chan_end_on_b: &ChannelEnd,
82 packet: Packet,
83 acknowledgement: Acknowledgement,
84) -> Result<(), ChannelError>
85where
86 ExecCtx: ExecutionContext,
87{
88 let conn_id_on_b = &chan_end_on_b.connection_hops()[0];
89
90 ctx_b.log_message("success: packet write acknowledgement".to_string())?;
91
92 let event = IbcEvent::WriteAcknowledgement(WriteAcknowledgement::new(
93 packet,
94 acknowledgement,
95 conn_id_on_b.clone(),
96 ));
97 ctx_b.emit_ibc_event(IbcEvent::Message(MessageEvent::Channel))?;
98 ctx_b.emit_ibc_event(event)?;
99
100 Ok(())
101}
102
103pub fn emit_packet_acknowledgement_event<ExecCtx>(
104 ctx_b: &mut ExecCtx,
105 packet: Packet,
106 acknowledgement: Acknowledgement,
107) -> Result<(), ChannelError>
108where
109 ExecCtx: ExecutionContext,
110{
111 let chan_end_path_on_b = ChannelEndPath::new(&packet.port_id_on_b, &packet.chan_id_on_b);
112 let chan_end_on_b = ctx_b.channel_end(&chan_end_path_on_b)?;
113
114 emit_packet_acknowledgement_event_with_chan_end(ctx_b, &chan_end_on_b, packet, acknowledgement)
115}
116
117pub fn acknowledgement_packet_validate<ValCtx>(
118 ctx_a: &ValCtx,
119 module: &dyn Module,
120 msg: MsgAcknowledgement,
121) -> Result<(), ChannelError>
122where
123 ValCtx: ValidationContext,
124{
125 validate(ctx_a, &msg)?;
126
127 module.on_acknowledgement_packet_validate(&msg.packet, &msg.acknowledgement, &msg.signer)
128}
129
130pub fn acknowledgement_packet_execute<ExecCtx>(
131 ctx_a: &mut ExecCtx,
132 module: &mut dyn Module,
133 msg: MsgAcknowledgement,
134) -> Result<(), ChannelError>
135where
136 ExecCtx: ExecutionContext,
137{
138 let chan_end_path_on_a =
139 ChannelEndPath::new(&msg.packet.port_id_on_a, &msg.packet.chan_id_on_a);
140 let chan_end_on_a = ctx_a.channel_end(&chan_end_path_on_a)?;
141 let conn_id_on_a = &chan_end_on_a.connection_hops()[0];
142
143 let event = IbcEvent::AcknowledgePacket(AcknowledgePacket::new(
145 msg.packet.clone(),
146 chan_end_on_a.ordering,
147 conn_id_on_a.clone(),
148 ));
149 ctx_a.emit_ibc_event(IbcEvent::Message(MessageEvent::Channel))?;
150 ctx_a.emit_ibc_event(event)?;
151
152 let commitment_path_on_a = CommitmentPath::new(
153 &msg.packet.port_id_on_a,
154 &msg.packet.chan_id_on_a,
155 msg.packet.seq_on_a,
156 );
157
158 if ctx_a.get_packet_commitment(&commitment_path_on_a).is_err() {
160 return Ok(());
165 };
166
167 let (extras, cb_result) =
168 module.on_acknowledgement_packet_execute(&msg.packet, &msg.acknowledgement, &msg.signer);
169
170 cb_result?;
171
172 {
174 ctx_a.delete_packet_commitment(&commitment_path_on_a)?;
175
176 if let Order::Ordered = chan_end_on_a.ordering {
177 let seq_ack_path_on_a =
180 SeqAckPath::new(&msg.packet.port_id_on_a, &msg.packet.chan_id_on_a);
181 ctx_a.store_next_sequence_ack(&seq_ack_path_on_a, msg.packet.seq_on_a.increment())?;
182 }
183 }
184
185 {
187 ctx_a.log_message("success: packet acknowledgement".to_string())?;
188
189 for module_event in extras.events {
192 ctx_a.emit_ibc_event(IbcEvent::Module(module_event))?
193 }
194
195 for log_message in extras.log {
196 ctx_a.log_message(log_message)?;
197 }
198 }
199
200 Ok(())
201}
202
203fn validate<Ctx>(ctx_a: &Ctx, msg: &MsgAcknowledgement) -> Result<(), ChannelError>
204where
205 Ctx: ValidationContext,
206{
207 ctx_a.validate_message_signer(&msg.signer)?;
208
209 let packet = &msg.packet;
210 let chan_end_path_on_a = ChannelEndPath::new(&packet.port_id_on_a, &packet.chan_id_on_a);
211 let chan_end_on_a = ctx_a.channel_end(&chan_end_path_on_a)?;
212
213 chan_end_on_a.verify_state_matches(&ChannelState::Open)?;
214
215 let counterparty = Counterparty::new(
216 packet.port_id_on_b.clone(),
217 Some(packet.chan_id_on_b.clone()),
218 );
219
220 chan_end_on_a.verify_counterparty_matches(&counterparty)?;
221
222 let conn_id_on_a = &chan_end_on_a.connection_hops()[0];
223 let conn_end_on_a = ctx_a.connection_end(conn_id_on_a)?;
224
225 conn_end_on_a.verify_state_matches(&ConnectionState::Open)?;
226
227 let commitment_path_on_a =
228 CommitmentPath::new(&packet.port_id_on_a, &packet.chan_id_on_a, packet.seq_on_a);
229
230 let Ok(commitment_on_a) = ctx_a.get_packet_commitment(&commitment_path_on_a) else {
232 return Ok(());
237 };
238
239 let expected_commitment_on_a = compute_packet_commitment(
240 &packet.data,
241 &packet.timeout_height_on_b,
242 &packet.timeout_timestamp_on_b,
243 );
244
245 if commitment_on_a != expected_commitment_on_a {
246 return Err(ChannelError::MismatchedPacketCommitment {
247 actual: commitment_on_a,
248 expected: expected_commitment_on_a,
249 });
250 }
251
252 if let Order::Ordered = chan_end_on_a.ordering {
253 let seq_ack_path_on_a = SeqAckPath::new(&packet.port_id_on_a, &packet.chan_id_on_a);
254 let next_seq_ack = ctx_a.get_next_sequence_ack(&seq_ack_path_on_a)?;
255 if packet.seq_on_a != next_seq_ack {
256 return Err(ChannelError::MismatchedPacketSequence {
257 actual: packet.seq_on_a,
258 expected: next_seq_ack,
259 });
260 }
261 }
262
263 {
265 let client_id_on_a = conn_end_on_a.client_id();
266
267 let client_val_ctx_a = ctx_a.get_client_validation_context();
268
269 let client_state_of_b_on_a = client_val_ctx_a.client_state(client_id_on_a)?;
270
271 client_state_of_b_on_a
272 .status(ctx_a.get_client_validation_context(), client_id_on_a)?
273 .verify_is_active()?;
274
275 client_state_of_b_on_a.validate_proof_height(msg.proof_height_on_b)?;
276
277 let client_cons_state_path_on_a = ClientConsensusStatePath::new(
278 client_id_on_a.clone(),
279 msg.proof_height_on_b.revision_number(),
280 msg.proof_height_on_b.revision_height(),
281 );
282 let consensus_state_of_b_on_a =
283 client_val_ctx_a.consensus_state(&client_cons_state_path_on_a)?;
284 let ack_commitment = compute_ack_commitment(&msg.acknowledgement);
285 let ack_path_on_b =
286 AckPath::new(&packet.port_id_on_b, &packet.chan_id_on_b, packet.seq_on_a);
287
288 verify_conn_delay_passed(ctx_a, msg.proof_height_on_b, &conn_end_on_a)?;
289
290 client_state_of_b_on_a.verify_membership(
292 conn_end_on_a.counterparty().prefix(),
293 &msg.proof_acked_on_b,
294 consensus_state_of_b_on_a.root(),
295 Path::Ack(ack_path_on_b),
296 ack_commitment.into_vec(),
297 )?;
298 }
299
300 Ok(())
301}