1use alloc::string::String;
2use core::marker::PhantomData;
3use core::time::Duration;
4
5use ibc::core::channel::types::acknowledgement::Acknowledgement;
6use ibc::core::channel::types::channel::Order;
7use ibc::core::channel::types::msgs::{
8 ChannelMsg, MsgAcknowledgement, MsgChannelCloseConfirm, MsgChannelCloseInit, MsgChannelOpenAck,
9 MsgChannelOpenConfirm, MsgChannelOpenInit, MsgChannelOpenTry, MsgRecvPacket, MsgTimeout,
10 MsgTimeoutOnClose, PacketMsg,
11};
12use ibc::core::channel::types::packet::Packet;
13use ibc::core::channel::types::timeout::TimeoutHeight;
14use ibc::core::channel::types::Version as ChannelVersion;
15use ibc::core::client::context::client_state::ClientStateValidation;
16use ibc::core::client::context::ClientValidationContext;
17use ibc::core::client::types::msgs::{ClientMsg, MsgCreateClient, MsgUpdateClient};
18use ibc::core::connection::types::msgs::{
19 ConnectionMsg, MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit,
20 MsgConnectionOpenTry,
21};
22use ibc::core::connection::types::version::Version as ConnectionVersion;
23use ibc::core::connection::types::Counterparty as ConnectionCounterParty;
24use ibc::core::handler::types::events::IbcEvent;
25use ibc::core::handler::types::msgs::MsgEnvelope;
26use ibc::core::host::types::identifiers::{ChannelId, ClientId, ConnectionId, PortId};
27use ibc::core::host::types::path::{
28 AckPath, ChannelEndPath, ClientConsensusStatePath, ClientStatePath, CommitmentPath,
29 ConnectionPath, ReceiptPath,
30};
31use ibc::core::host::ValidationContext;
32use ibc::primitives::Signer;
33use ibc_query::core::context::ProvableContext;
34
35use crate::context::TestContext;
36use crate::hosts::{HostClientState, TestBlock, TestHost};
37use crate::testapp::ibc::core::types::{dummy_light_client, DefaultIbcStore};
38
39#[derive(Debug, Default)]
46pub struct TypedRelayerOps<A, B>(PhantomData<A>, PhantomData<B>)
47where
48 A: TestHost,
49 B: TestHost,
50 HostClientState<A>: ClientStateValidation<DefaultIbcStore>,
51 HostClientState<B>: ClientStateValidation<DefaultIbcStore>;
52
53impl<A, B> TypedRelayerOps<A, B>
54where
55 A: TestHost,
56 B: TestHost,
57 HostClientState<A>: ClientStateValidation<DefaultIbcStore>,
58 HostClientState<B>: ClientStateValidation<DefaultIbcStore>,
59{
60 pub fn create_client_on_a(
63 ctx_a: &mut TestContext<A>,
64 ctx_b: &TestContext<B>,
65 signer: Signer,
66 ) -> ClientId {
67 let light_client_of_b = dummy_light_client(ctx_b).call();
68
69 let msg_for_a = MsgEnvelope::Client(ClientMsg::CreateClient(MsgCreateClient {
70 client_state: light_client_of_b.client_state.into(),
71 consensus_state: light_client_of_b
72 .consensus_states
73 .values()
74 .next()
75 .expect("at least one")
76 .clone()
77 .into(),
78 signer,
79 }));
80
81 ctx_a.deliver(msg_for_a).expect("success");
82
83 let Some(IbcEvent::CreateClient(create_client_b_event)) =
84 ctx_a.ibc_store().events.lock().last().cloned()
85 else {
86 panic!("unexpected event")
87 };
88
89 let client_id_on_a = create_client_b_event.client_id().clone();
90
91 assert_eq!(
92 ValidationContext::get_client_validation_context(ctx_a.ibc_store())
93 .client_state(&client_id_on_a)
94 .expect("client state exists")
95 .latest_height(),
96 ctx_b.latest_height()
97 );
98
99 client_id_on_a
100 }
101
102 pub fn sync_clock_on_a(ctx_a: &mut TestContext<A>, ctx_b: &TestContext<B>) {
104 while ctx_b.latest_timestamp() > ctx_a.latest_timestamp() {
105 ctx_a.advance_block_height();
106 }
107 }
108
109 pub fn update_client_on_a(
111 ctx_a: &mut TestContext<A>,
112 ctx_b: &TestContext<B>,
113 client_id_on_a: ClientId,
114 signer: Signer,
115 ) {
116 let trusted_height_of_b = ctx_a
117 .ibc_store()
118 .get_client_validation_context()
119 .client_state(&client_id_on_a)
120 .expect("client state exists")
121 .latest_height();
122
123 let trusted_block_of_b = ctx_b
124 .host
125 .get_block(&trusted_height_of_b)
126 .expect("block exists");
127
128 let target_height_of_b = ctx_b.latest_height();
129
130 let target_block_of_b = ctx_b.host_block(&target_height_of_b).expect("block exists");
131
132 let msg_for_a = MsgEnvelope::Client(ClientMsg::UpdateClient(MsgUpdateClient {
133 client_id: client_id_on_a.clone(),
134 client_message: target_block_of_b
135 .into_header_with_trusted(&trusted_block_of_b)
136 .into(),
137 signer,
138 }));
139
140 ctx_a.deliver(msg_for_a).expect("success");
141
142 let Some(IbcEvent::UpdateClient(_)) = ctx_a.ibc_store().events.lock().last().cloned()
143 else {
144 panic!("unexpected event")
145 };
146 }
147
148 pub fn update_client_on_a_with_sync(
152 ctx_a: &mut TestContext<A>,
153 ctx_b: &mut TestContext<B>,
154 client_id_on_a: ClientId,
155 signer: Signer,
156 ) {
157 TypedRelayerOps::<A, B>::sync_clock_on_a(ctx_a, ctx_b);
158 TypedRelayerOps::<A, B>::update_client_on_a(ctx_a, ctx_b, client_id_on_a, signer);
159 }
160
161 pub fn connection_open_init_on_a(
164 ctx_a: &mut TestContext<A>,
165 ctx_b: &TestContext<B>,
166 client_id_on_a: ClientId,
167 client_id_on_b: ClientId,
168 signer: Signer,
169 ) -> ConnectionId {
170 let counterparty_b = ConnectionCounterParty::new(
171 client_id_on_b.clone(),
172 None,
173 ctx_b.ibc_store().commitment_prefix(),
174 );
175
176 let msg_for_a = MsgEnvelope::Connection(ConnectionMsg::OpenInit(MsgConnectionOpenInit {
177 client_id_on_a: client_id_on_a.clone(),
178 counterparty: counterparty_b,
179 version: None,
180 delay_period: Duration::from_secs(0),
181 signer: signer.clone(),
182 }));
183
184 ctx_a.deliver(msg_for_a).expect("success");
185
186 let Some(IbcEvent::OpenInitConnection(open_init_connection_event)) =
187 ctx_a.ibc_store().events.lock().last().cloned()
188 else {
189 panic!("unexpected event")
190 };
191
192 open_init_connection_event.conn_id_on_a().clone()
193 }
194
195 pub fn connection_open_try_on_b(
198 ctx_b: &mut TestContext<B>,
199 ctx_a: &TestContext<A>,
200 conn_id_on_a: ConnectionId,
201 client_id_on_a: ClientId,
202 client_id_on_b: ClientId,
203 signer: Signer,
204 ) -> ConnectionId {
205 let proofs_height_on_a = ctx_a.latest_height();
206
207 let client_state_of_b_on_a = ctx_a
208 .ibc_store()
209 .client_state(&client_id_on_a)
210 .expect("client state exists");
211
212 let consensus_height_of_b_on_a = client_state_of_b_on_a.latest_height();
213
214 let counterparty_a = ConnectionCounterParty::new(
215 client_id_on_a.clone(),
216 Some(conn_id_on_a.clone()),
217 ctx_a.ibc_store().commitment_prefix(),
218 );
219
220 let proof_conn_end_on_a = ctx_a
221 .ibc_store()
222 .get_proof(
223 proofs_height_on_a,
224 &ConnectionPath::new(&conn_id_on_a).into(),
225 )
226 .expect("connection end exists")
227 .try_into()
228 .expect("value merkle proof");
229
230 let proof_client_state_of_b_on_a = ctx_a
231 .ibc_store()
232 .get_proof(
233 proofs_height_on_a,
234 &ClientStatePath::new(client_id_on_a.clone()).into(),
235 )
236 .expect("client state exists")
237 .try_into()
238 .expect("value merkle proof");
239
240 let proof_consensus_state_of_b_on_a = ctx_a
241 .ibc_store()
242 .get_proof(
243 proofs_height_on_a,
244 &ClientConsensusStatePath::new(
245 client_id_on_a.clone(),
246 consensus_height_of_b_on_a.revision_number(),
247 consensus_height_of_b_on_a.revision_height(),
248 )
249 .into(),
250 )
251 .expect("consensus state exists")
252 .try_into()
253 .expect("value merkle proof");
254
255 #[allow(deprecated)]
256 let msg_for_b = MsgEnvelope::Connection(ConnectionMsg::OpenTry(MsgConnectionOpenTry {
257 client_id_on_b: client_id_on_b.clone(),
258 client_state_of_b_on_a: client_state_of_b_on_a.into(),
259 counterparty: counterparty_a,
260 versions_on_a: ConnectionVersion::compatibles(),
261 proof_conn_end_on_a,
262 proof_client_state_of_b_on_a,
263 proof_consensus_state_of_b_on_a,
264 proofs_height_on_a,
265 consensus_height_of_b_on_a,
266 delay_period: Duration::from_secs(0),
267 signer: signer.clone(),
268 proof_consensus_state_of_b: None,
269 previous_connection_id: String::new(),
271 }));
272
273 ctx_b.deliver(msg_for_b).expect("success");
274
275 let Some(IbcEvent::OpenTryConnection(open_try_connection_event)) =
276 ctx_b.ibc_store().events.lock().last().cloned()
277 else {
278 panic!("unexpected event")
279 };
280
281 open_try_connection_event.conn_id_on_b().clone()
282 }
283
284 pub fn connection_open_ack_on_a(
287 ctx_a: &mut TestContext<A>,
288 ctx_b: &TestContext<B>,
289 conn_id_on_a: ConnectionId,
290 conn_id_on_b: ConnectionId,
291 client_id_on_b: ClientId,
292 signer: Signer,
293 ) {
294 let proofs_height_on_b = ctx_b.latest_height();
295
296 let client_state_of_a_on_b = ctx_b
297 .ibc_store()
298 .client_state(&client_id_on_b)
299 .expect("client state exists");
300
301 let consensus_height_of_a_on_b = client_state_of_a_on_b.latest_height();
302
303 let proof_conn_end_on_b = ctx_b
304 .ibc_store()
305 .get_proof(
306 proofs_height_on_b,
307 &ConnectionPath::new(&conn_id_on_b).into(),
308 )
309 .expect("connection end exists")
310 .try_into()
311 .expect("value merkle proof");
312
313 let proof_client_state_of_a_on_b = ctx_b
314 .ibc_store()
315 .get_proof(
316 proofs_height_on_b,
317 &ClientStatePath::new(client_id_on_b.clone()).into(),
318 )
319 .expect("client state exists")
320 .try_into()
321 .expect("value merkle proof");
322
323 let proof_consensus_state_of_a_on_b = ctx_b
324 .ibc_store()
325 .get_proof(
326 proofs_height_on_b,
327 &ClientConsensusStatePath::new(
328 client_id_on_b.clone(),
329 consensus_height_of_a_on_b.revision_number(),
330 consensus_height_of_a_on_b.revision_height(),
331 )
332 .into(),
333 )
334 .expect("consensus state exists")
335 .try_into()
336 .expect("value merkle proof");
337
338 let msg_for_a = MsgEnvelope::Connection(ConnectionMsg::OpenAck(MsgConnectionOpenAck {
339 conn_id_on_a: conn_id_on_a.clone(),
340 conn_id_on_b: conn_id_on_b.clone(),
341 client_state_of_a_on_b: client_state_of_a_on_b.into(),
342 proof_conn_end_on_b,
343 proof_client_state_of_a_on_b,
344 proof_consensus_state_of_a_on_b,
345 proofs_height_on_b,
346 consensus_height_of_a_on_b,
347 version: ConnectionVersion::compatibles()[0].clone(),
348 signer: signer.clone(),
349 proof_consensus_state_of_a: None,
350 }));
351
352 ctx_a.deliver(msg_for_a).expect("success");
353
354 let Some(IbcEvent::OpenAckConnection(_)) = ctx_a.ibc_store().events.lock().last().cloned()
355 else {
356 panic!("unexpected event")
357 };
358 }
359
360 pub fn connection_open_confirm_on_b(
363 ctx_b: &mut TestContext<B>,
364 ctx_a: &TestContext<A>,
365 conn_id_on_a: ConnectionId,
366 conn_id_on_b: ConnectionId,
367 signer: Signer,
368 ) {
369 let proof_height_on_a = ctx_a.latest_height();
370
371 let proof_conn_end_on_a = ctx_a
372 .ibc_store()
373 .get_proof(
374 proof_height_on_a,
375 &ConnectionPath::new(&conn_id_on_a).into(),
376 )
377 .expect("connection end exists")
378 .try_into()
379 .expect("value merkle proof");
380
381 let msg_for_b =
382 MsgEnvelope::Connection(ConnectionMsg::OpenConfirm(MsgConnectionOpenConfirm {
383 conn_id_on_b: conn_id_on_b.clone(),
384 proof_conn_end_on_a,
385 proof_height_on_a,
386 signer: signer.clone(),
387 }));
388
389 ctx_b.deliver(msg_for_b).expect("success");
390
391 let Some(IbcEvent::OpenConfirmConnection(_)) = ctx_b.ibc_store().events.lock().last()
392 else {
393 panic!("unexpected event")
394 };
395 }
396
397 pub fn create_connection_on_a(
400 ctx_a: &mut TestContext<A>,
401 ctx_b: &mut TestContext<B>,
402 client_id_on_a: ClientId,
403 client_id_on_b: ClientId,
404 signer: Signer,
405 ) -> (ConnectionId, ConnectionId) {
406 let conn_id_on_a = TypedRelayerOps::<A, B>::connection_open_init_on_a(
407 ctx_a,
408 ctx_b,
409 client_id_on_a.clone(),
410 client_id_on_b.clone(),
411 signer.clone(),
412 );
413
414 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
415 ctx_b,
416 ctx_a,
417 client_id_on_b.clone(),
418 signer.clone(),
419 );
420
421 let conn_id_on_b = TypedRelayerOps::<A, B>::connection_open_try_on_b(
422 ctx_b,
423 ctx_a,
424 conn_id_on_a.clone(),
425 client_id_on_a.clone(),
426 client_id_on_b.clone(),
427 signer.clone(),
428 );
429
430 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(
431 ctx_a,
432 ctx_b,
433 client_id_on_a.clone(),
434 signer.clone(),
435 );
436
437 TypedRelayerOps::<A, B>::connection_open_ack_on_a(
438 ctx_a,
439 ctx_b,
440 conn_id_on_a.clone(),
441 conn_id_on_b.clone(),
442 client_id_on_b.clone(),
443 signer.clone(),
444 );
445
446 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
447 ctx_b,
448 ctx_a,
449 client_id_on_b.clone(),
450 signer.clone(),
451 );
452
453 TypedRelayerOps::<A, B>::connection_open_confirm_on_b(
454 ctx_b,
455 ctx_a,
456 conn_id_on_b.clone(),
457 conn_id_on_a.clone(),
458 signer.clone(),
459 );
460
461 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(ctx_a, ctx_b, client_id_on_a, signer);
462
463 (conn_id_on_a, conn_id_on_b)
464 }
465
466 pub fn channel_open_init_on_a(
469 ctx_a: &mut TestContext<A>,
470 conn_id_on_a: ConnectionId,
471 port_id_on_a: PortId,
472 port_id_on_b: PortId,
473 signer: Signer,
474 ) -> ChannelId {
475 let msg_for_a = MsgEnvelope::Channel(ChannelMsg::OpenInit(MsgChannelOpenInit {
476 port_id_on_a,
477 connection_hops_on_a: [conn_id_on_a].to_vec(),
478 port_id_on_b,
479 ordering: Order::Unordered,
480 signer,
481 version_proposal: ChannelVersion::empty(),
482 }));
483
484 ctx_a.deliver(msg_for_a).expect("success");
485
486 let Some(IbcEvent::OpenInitChannel(open_init_channel_event)) =
487 ctx_a.ibc_store().events.lock().last().cloned()
488 else {
489 panic!("unexpected event")
490 };
491
492 open_init_channel_event.chan_id_on_a().clone()
493 }
494
495 pub fn channel_open_try_on_b(
498 ctx_b: &mut TestContext<B>,
499 ctx_a: &TestContext<A>,
500 conn_id_on_b: ConnectionId,
501 chan_id_on_a: ChannelId,
502 port_id_on_a: PortId,
503 signer: Signer,
504 ) -> ChannelId {
505 let proof_height_on_a = ctx_a.latest_height();
506
507 let proof_chan_end_on_a = ctx_a
508 .ibc_store()
509 .get_proof(
510 proof_height_on_a,
511 &ChannelEndPath::new(&port_id_on_a, &chan_id_on_a).into(),
512 )
513 .expect("connection end exists")
514 .try_into()
515 .expect("value merkle proof");
516
517 #[allow(deprecated)]
518 let msg_for_b = MsgEnvelope::Channel(ChannelMsg::OpenTry(MsgChannelOpenTry {
519 port_id_on_b: PortId::transfer(),
520 connection_hops_on_b: [conn_id_on_b].to_vec(),
521 port_id_on_a: PortId::transfer(),
522 chan_id_on_a,
523 version_supported_on_a: ChannelVersion::empty(),
524 proof_chan_end_on_a,
525 proof_height_on_a,
526 ordering: Order::Unordered,
527 signer,
528
529 version_proposal: ChannelVersion::empty(),
530 }));
531
532 ctx_b.deliver(msg_for_b).expect("success");
533
534 let Some(IbcEvent::OpenTryChannel(open_try_channel_event)) =
535 ctx_b.ibc_store().events.lock().last().cloned()
536 else {
537 panic!("unexpected event")
538 };
539
540 open_try_channel_event.chan_id_on_b().clone()
541 }
542
543 pub fn channel_open_ack_on_a(
546 ctx_a: &mut TestContext<A>,
547 ctx_b: &TestContext<B>,
548 chan_id_on_a: ChannelId,
549 port_id_on_a: PortId,
550 chan_id_on_b: ChannelId,
551 port_id_on_b: PortId,
552 signer: Signer,
553 ) {
554 let proof_height_on_b = ctx_b.latest_height();
555
556 let proof_chan_end_on_b = ctx_b
557 .ibc_store()
558 .get_proof(
559 proof_height_on_b,
560 &ChannelEndPath::new(&port_id_on_b, &chan_id_on_b).into(),
561 )
562 .expect("connection end exists")
563 .try_into()
564 .expect("value merkle proof");
565
566 let msg_for_a = MsgEnvelope::Channel(ChannelMsg::OpenAck(MsgChannelOpenAck {
567 port_id_on_a,
568 chan_id_on_a,
569 chan_id_on_b,
570 version_on_b: ChannelVersion::empty(),
571 proof_chan_end_on_b,
572 proof_height_on_b,
573 signer,
574 }));
575
576 ctx_a.deliver(msg_for_a).expect("success");
577
578 let Some(IbcEvent::OpenAckChannel(_)) = ctx_a.ibc_store().events.lock().last().cloned()
579 else {
580 panic!("unexpected event")
581 };
582 }
583
584 pub fn channel_open_confirm_on_b(
587 ctx_b: &mut TestContext<B>,
588 ctx_a: &TestContext<A>,
589 chan_id_on_a: ChannelId,
590 chan_id_on_b: ChannelId,
591 port_id_on_b: PortId,
592 signer: Signer,
593 ) {
594 let proof_height_on_a = ctx_a.latest_height();
595
596 let proof_chan_end_on_a = ctx_a
597 .ibc_store()
598 .get_proof(
599 proof_height_on_a,
600 &ChannelEndPath::new(&PortId::transfer(), &chan_id_on_a).into(),
601 )
602 .expect("connection end exists")
603 .try_into()
604 .expect("value merkle proof");
605
606 let msg_for_b = MsgEnvelope::Channel(ChannelMsg::OpenConfirm(MsgChannelOpenConfirm {
607 port_id_on_b,
608 chan_id_on_b,
609 proof_chan_end_on_a,
610 proof_height_on_a,
611 signer,
612 }));
613
614 ctx_b.deliver(msg_for_b).expect("success");
615
616 let Some(IbcEvent::OpenConfirmChannel(_)) = ctx_b.ibc_store().events.lock().last().cloned()
617 else {
618 panic!("unexpected event")
619 };
620 }
621
622 pub fn channel_close_init_on_a(
625 ctx_a: &mut TestContext<A>,
626 chan_id_on_a: ChannelId,
627 port_id_on_a: PortId,
628 signer: Signer,
629 ) {
630 let msg_for_a = MsgEnvelope::Channel(ChannelMsg::CloseInit(MsgChannelCloseInit {
631 port_id_on_a,
632 chan_id_on_a,
633 signer,
634 }));
635
636 ctx_a.deliver(msg_for_a).expect("success");
637
638 let Some(IbcEvent::CloseInitChannel(_)) = ctx_a.ibc_store().events.lock().last().cloned()
639 else {
640 panic!("unexpected event")
641 };
642 }
643
644 pub fn channel_close_confirm_on_b(
647 ctx_b: &mut TestContext<B>,
648 ctx_a: &TestContext<A>,
649 chan_id_on_b: ChannelId,
650 port_id_on_b: PortId,
651 signer: Signer,
652 ) {
653 let proof_height_on_a = ctx_a.latest_height();
654
655 let proof_chan_end_on_a = ctx_a
656 .ibc_store()
657 .get_proof(
658 proof_height_on_a,
659 &ChannelEndPath::new(&PortId::transfer(), &chan_id_on_b).into(),
660 )
661 .expect("connection end exists")
662 .try_into()
663 .expect("value merkle proof");
664
665 let msg_for_b = MsgEnvelope::Channel(ChannelMsg::CloseConfirm(MsgChannelCloseConfirm {
666 port_id_on_b,
667 chan_id_on_b,
668 proof_chan_end_on_a,
669 proof_height_on_a,
670 signer,
671 }));
672
673 ctx_b.deliver(msg_for_b).expect("success");
674
675 let Some(IbcEvent::CloseConfirmChannel(_)) =
676 ctx_b.ibc_store().events.lock().last().cloned()
677 else {
678 panic!("unexpected event")
679 };
680 }
681
682 #[allow(clippy::too_many_arguments)]
685 pub fn create_channel_on_a(
686 ctx_a: &mut TestContext<A>,
687 ctx_b: &mut TestContext<B>,
688 client_id_on_a: ClientId,
689 conn_id_on_a: ConnectionId,
690 port_id_on_a: PortId,
691 client_id_on_b: ClientId,
692 conn_id_on_b: ConnectionId,
693 port_id_on_b: PortId,
694 signer: Signer,
695 ) -> (ChannelId, ChannelId) {
696 let chan_id_on_a = TypedRelayerOps::<A, B>::channel_open_init_on_a(
697 ctx_a,
698 conn_id_on_a.clone(),
699 port_id_on_a.clone(),
700 port_id_on_b.clone(),
701 signer.clone(),
702 );
703
704 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
705 ctx_b,
706 ctx_a,
707 client_id_on_b.clone(),
708 signer.clone(),
709 );
710
711 let chan_id_on_b = TypedRelayerOps::<A, B>::channel_open_try_on_b(
712 ctx_b,
713 ctx_a,
714 conn_id_on_b.clone(),
715 chan_id_on_a.clone(),
716 port_id_on_a.clone(),
717 signer.clone(),
718 );
719
720 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(
721 ctx_a,
722 ctx_b,
723 client_id_on_a.clone(),
724 signer.clone(),
725 );
726
727 TypedRelayerOps::<A, B>::channel_open_ack_on_a(
728 ctx_a,
729 ctx_b,
730 chan_id_on_a.clone(),
731 port_id_on_a.clone(),
732 chan_id_on_b.clone(),
733 port_id_on_b.clone(),
734 signer.clone(),
735 );
736
737 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
738 ctx_b,
739 ctx_a,
740 client_id_on_b.clone(),
741 signer.clone(),
742 );
743
744 TypedRelayerOps::<A, B>::channel_open_confirm_on_b(
745 ctx_b,
746 ctx_a,
747 chan_id_on_a.clone(),
748 chan_id_on_b.clone(),
749 port_id_on_b,
750 signer.clone(),
751 );
752
753 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(ctx_a, ctx_b, client_id_on_a, signer);
754
755 (chan_id_on_a, chan_id_on_b)
756 }
757
758 #[allow(clippy::too_many_arguments)]
760 pub fn close_channel_on_a(
761 ctx_a: &mut TestContext<A>,
762 ctx_b: &mut TestContext<B>,
763 client_id_on_a: ClientId,
764 chan_id_on_a: ChannelId,
765 port_id_on_a: PortId,
766 client_id_on_b: ClientId,
767 chan_id_on_b: ChannelId,
768 port_id_on_b: PortId,
769 signer: Signer,
770 ) {
771 TypedRelayerOps::<A, B>::channel_close_init_on_a(
772 ctx_a,
773 chan_id_on_a.clone(),
774 port_id_on_a.clone(),
775 signer.clone(),
776 );
777
778 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
779 ctx_b,
780 ctx_a,
781 client_id_on_b,
782 signer.clone(),
783 );
784
785 TypedRelayerOps::<A, B>::channel_close_confirm_on_b(
786 ctx_b,
787 ctx_a,
788 chan_id_on_b,
789 port_id_on_b,
790 signer.clone(),
791 );
792
793 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(ctx_a, ctx_b, client_id_on_a, signer);
794 }
795
796 pub fn packet_recv_on_b(
799 ctx_b: &mut TestContext<B>,
800 ctx_a: &TestContext<A>,
801 packet: Packet,
802 signer: Signer,
803 ) -> Acknowledgement {
804 let proof_height_on_a = ctx_a.latest_height();
805
806 let proof_commitment_on_a = ctx_a
807 .ibc_store()
808 .get_proof(
809 proof_height_on_a,
810 &CommitmentPath::new(&packet.port_id_on_a, &packet.chan_id_on_a, packet.seq_on_a)
811 .into(),
812 )
813 .expect("commitment proof exists")
814 .try_into()
815 .expect("value merkle proof");
816
817 let msg_for_b = MsgEnvelope::Packet(PacketMsg::Recv(MsgRecvPacket {
818 packet,
819 proof_commitment_on_a,
820 proof_height_on_a,
821 signer,
822 }));
823
824 ctx_b.deliver(msg_for_b).expect("success");
825
826 let Some(IbcEvent::WriteAcknowledgement(write_ack_event)) =
827 ctx_b.ibc_store().events.lock().last().cloned()
828 else {
829 panic!("unexpected event")
830 };
831
832 write_ack_event.acknowledgement().clone()
833 }
834
835 pub fn packet_ack_on_a(
837 ctx_a: &mut TestContext<A>,
838 ctx_b: &TestContext<B>,
839 packet: Packet,
840 acknowledgement: Acknowledgement,
841 signer: Signer,
842 ) {
843 let proof_height_on_b = ctx_b.latest_height();
844
845 let proof_acked_on_b = ctx_b
846 .ibc_store()
847 .get_proof(
848 proof_height_on_b,
849 &AckPath::new(&packet.port_id_on_b, &packet.chan_id_on_b, packet.seq_on_a).into(),
850 )
851 .expect("acknowledgement proof exists")
852 .try_into()
853 .expect("value merkle proof");
854
855 let msg_for_a = MsgEnvelope::Packet(PacketMsg::Ack(MsgAcknowledgement {
856 packet,
857 acknowledgement,
858 proof_acked_on_b,
859 proof_height_on_b,
860 signer,
861 }));
862
863 ctx_a.deliver(msg_for_a).expect("success");
864
865 let Some(IbcEvent::AcknowledgePacket(_)) = ctx_a.ibc_store().events.lock().last().cloned()
866 else {
867 panic!("unexpected event")
868 };
869 }
870
871 pub fn packet_timeout_on_a(
874 ctx_a: &mut TestContext<A>,
875 ctx_b: &TestContext<B>,
876 packet: Packet,
877 signer: Signer,
878 ) {
879 let proof_height_on_b = ctx_b.latest_height();
880
881 let proof_unreceived_on_b = ctx_b
882 .ibc_store()
883 .get_proof(
884 proof_height_on_b,
885 &ReceiptPath::new(&packet.port_id_on_b, &packet.chan_id_on_b, packet.seq_on_a)
886 .into(),
887 )
888 .expect("non-membership receipt proof exists")
889 .try_into()
890 .expect("value merkle proof");
891
892 let msg_for_a = MsgEnvelope::Packet(PacketMsg::Timeout(MsgTimeout {
893 next_seq_recv_on_b: packet.seq_on_a,
894 packet,
895 proof_unreceived_on_b,
896 proof_height_on_b,
897 signer,
898 }));
899
900 ctx_a.deliver(msg_for_a).expect("success");
901
902 let Some(IbcEvent::TimeoutPacket(_)) = ctx_a.ibc_store().events.lock().last().cloned()
903 else {
904 panic!("unexpected event")
905 };
906 }
907
908 pub fn packet_timeout_on_close_on_a(
911 ctx_a: &mut TestContext<A>,
912 ctx_b: &TestContext<B>,
913 packet: Packet,
914 chan_id_on_b: ChannelId,
915 port_id_on_b: PortId,
916 signer: Signer,
917 ) {
918 let proof_height_on_b = ctx_b.latest_height();
919
920 let proof_unreceived_on_b = ctx_b
921 .ibc_store()
922 .get_proof(
923 proof_height_on_b,
924 &ReceiptPath::new(&port_id_on_b, &chan_id_on_b, packet.seq_on_a).into(),
925 )
926 .expect("non-membership receipt proof")
927 .try_into()
928 .expect("value merkle proof");
929
930 let proof_close_on_b = ctx_b
931 .ibc_store()
932 .get_proof(
933 proof_height_on_b,
934 &ChannelEndPath::new(&port_id_on_b, &chan_id_on_b).into(),
935 )
936 .expect("channel end data exists")
937 .try_into()
938 .expect("value merkle proof");
939
940 let msg_for_a = MsgEnvelope::Packet(PacketMsg::TimeoutOnClose(MsgTimeoutOnClose {
941 next_seq_recv_on_b: packet.seq_on_a,
942 packet,
943 proof_unreceived_on_b,
944 proof_close_on_b,
945 proof_height_on_b,
946 signer,
947 }));
948
949 ctx_a.deliver(msg_for_a).expect("success");
950
951 let Some(IbcEvent::TimeoutPacket(_)) = ctx_a.ibc_store().events.lock().last().cloned()
952 else {
953 panic!("unexpected event")
954 };
955 }
956
957 pub fn submit_packet_on_b(
959 ctx_a: &mut TestContext<A>,
960 ctx_b: &mut TestContext<B>,
961 packet: Packet,
962 client_id_on_a: ClientId,
963 client_id_on_b: ClientId,
964 signer: Signer,
965 ) {
966 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
969 ctx_b,
970 ctx_a,
971 client_id_on_b.clone(),
972 signer.clone(),
973 );
974
975 let acknowledgement =
976 TypedRelayerOps::<A, B>::packet_recv_on_b(ctx_b, ctx_a, packet.clone(), signer.clone());
977
978 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(
979 ctx_a,
980 ctx_b,
981 client_id_on_a,
982 signer.clone(),
983 );
984
985 TypedRelayerOps::<A, B>::packet_ack_on_a(
986 ctx_a,
987 ctx_b,
988 packet,
989 acknowledgement,
990 signer.clone(),
991 );
992
993 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
994 ctx_b,
995 ctx_a,
996 client_id_on_b,
997 signer.clone(),
998 );
999 }
1000
1001 pub fn timeout_packet_from_a(
1003 ctx_a: &mut TestContext<A>,
1004 ctx_b: &mut TestContext<B>,
1005 packet: Packet,
1006 client_id_on_a: ClientId,
1007 client_id_on_b: ClientId,
1008 signer: Signer,
1009 ) {
1010 let TimeoutHeight::At(timeout_height) = packet.timeout_height_on_b else {
1013 panic!("timeout height is set")
1014 };
1015
1016 while ctx_b.latest_height() <= timeout_height {
1019 ctx_b.advance_block_height();
1020 }
1021
1022 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(
1024 ctx_a,
1025 ctx_b,
1026 client_id_on_a.clone(),
1027 signer.clone(),
1028 );
1029
1030 TypedRelayerOps::<A, B>::packet_timeout_on_a(ctx_a, ctx_b, packet.clone(), signer.clone());
1032
1033 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
1035 ctx_b,
1036 ctx_a,
1037 client_id_on_b,
1038 signer.clone(),
1039 );
1040 }
1041
1042 pub fn timeout_packet_from_a_on_channel_close(
1044 ctx_a: &mut TestContext<A>,
1045 ctx_b: &mut TestContext<B>,
1046 packet: Packet,
1047 client_id_on_a: ClientId,
1048 client_id_on_b: ClientId,
1049 signer: Signer,
1050 ) {
1051 TypedRelayerOps::<A, B>::close_channel_on_a(
1055 ctx_a,
1056 ctx_b,
1057 client_id_on_a.clone(),
1058 packet.chan_id_on_a.clone(),
1059 packet.port_id_on_a.clone(),
1060 client_id_on_b.clone(),
1061 packet.chan_id_on_b.clone(),
1062 packet.port_id_on_b.clone(),
1063 signer.clone(),
1064 );
1065
1066 TypedRelayerOps::<A, B>::packet_timeout_on_close_on_a(
1068 ctx_a,
1069 ctx_b,
1070 packet.clone(),
1071 packet.chan_id_on_b.clone(),
1072 packet.port_id_on_b.clone(),
1073 signer.clone(),
1074 );
1075
1076 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
1078 ctx_b,
1079 ctx_a,
1080 client_id_on_b,
1081 signer.clone(),
1082 );
1083 }
1084}