1use ibc::core::channel::types::packet::Packet;
2use ibc::core::client::context::client_state::ClientStateValidation;
3use ibc::core::host::types::identifiers::{ChannelId, ClientId, ConnectionId, PortId};
4use ibc::core::host::types::path::ChannelEndPath;
5use ibc::core::host::ValidationContext;
6use ibc::primitives::Signer;
7
8use crate::context::TestContext;
9use crate::hosts::{HostClientState, TestHost};
10use crate::relayer::utils::TypedRelayerOps;
11use crate::testapp::ibc::core::types::DefaultIbcStore;
12
13pub struct RelayerContext<A, B>
15where
16 A: TestHost,
17 B: TestHost,
18 HostClientState<A>: ClientStateValidation<DefaultIbcStore>,
19 HostClientState<B>: ClientStateValidation<DefaultIbcStore>,
20{
21 ctx_a: TestContext<A>,
22 ctx_b: TestContext<B>,
23}
24
25impl<A, B> RelayerContext<A, B>
26where
27 A: TestHost,
28 B: TestHost,
29 HostClientState<A>: ClientStateValidation<DefaultIbcStore>,
30 HostClientState<B>: ClientStateValidation<DefaultIbcStore>,
31{
32 pub fn new(ctx_a: TestContext<A>, ctx_b: TestContext<B>) -> Self {
34 Self { ctx_a, ctx_b }
35 }
36
37 pub fn get_ctx_a(&self) -> &TestContext<A> {
39 &self.ctx_a
40 }
41
42 pub fn get_ctx_b(&self) -> &TestContext<B> {
44 &self.ctx_b
45 }
46
47 pub fn get_ctx_a_mut(&mut self) -> &mut TestContext<A> {
49 &mut self.ctx_a
50 }
51
52 pub fn get_ctx_b_mut(&mut self) -> &mut TestContext<B> {
54 &mut self.ctx_b
55 }
56
57 pub fn create_client_on_a(&mut self, signer: Signer) -> ClientId {
60 TypedRelayerOps::<A, B>::create_client_on_a(&mut self.ctx_a, &self.ctx_b, signer)
61 }
62
63 pub fn create_client_on_b(&mut self, signer: Signer) -> ClientId {
66 TypedRelayerOps::<B, A>::create_client_on_a(&mut self.ctx_b, &self.ctx_a, signer)
67 }
68
69 pub fn update_client_on_a_with_sync(&mut self, client_id_on_a: ClientId, signer: Signer) {
71 TypedRelayerOps::<A, B>::update_client_on_a_with_sync(
72 &mut self.ctx_a,
73 &mut self.ctx_b,
74 client_id_on_a,
75 signer,
76 )
77 }
78
79 pub fn update_client_on_b_with_sync(&mut self, client_id_on_b: ClientId, signer: Signer) {
81 TypedRelayerOps::<B, A>::update_client_on_a_with_sync(
82 &mut self.ctx_b,
83 &mut self.ctx_a,
84 client_id_on_b,
85 signer,
86 )
87 }
88
89 pub fn create_connection_on_a(
92 &mut self,
93 client_id_on_a: ClientId,
94 client_id_on_b: ClientId,
95 signer: Signer,
96 ) -> (ConnectionId, ConnectionId) {
97 TypedRelayerOps::<A, B>::create_connection_on_a(
98 &mut self.ctx_a,
99 &mut self.ctx_b,
100 client_id_on_a,
101 client_id_on_b,
102 signer,
103 )
104 }
105
106 pub fn create_connection_on_b(
109 &mut self,
110 client_id_on_b: ClientId,
111 client_id_on_a: ClientId,
112 signer: Signer,
113 ) -> (ConnectionId, ConnectionId) {
114 TypedRelayerOps::<B, A>::create_connection_on_a(
115 &mut self.ctx_b,
116 &mut self.ctx_a,
117 client_id_on_b,
118 client_id_on_a,
119 signer,
120 )
121 }
122
123 pub fn create_channel_on_a(
126 &mut self,
127 conn_id_on_a: ConnectionId,
128 port_id_on_a: PortId,
129 conn_id_on_b: ConnectionId,
130 port_id_on_b: PortId,
131 signer: Signer,
132 ) -> (ChannelId, ChannelId) {
133 let client_id_on_a = self
134 .ctx_a
135 .ibc_store()
136 .connection_end(&conn_id_on_a)
137 .expect("connection exists")
138 .client_id()
139 .clone();
140
141 let client_id_on_b = self
142 .ctx_b
143 .ibc_store()
144 .connection_end(&conn_id_on_b)
145 .expect("connection exists")
146 .client_id()
147 .clone();
148
149 TypedRelayerOps::<A, B>::create_channel_on_a(
150 &mut self.ctx_a,
151 &mut self.ctx_b,
152 client_id_on_a,
153 conn_id_on_a,
154 port_id_on_a,
155 client_id_on_b,
156 conn_id_on_b,
157 port_id_on_b,
158 signer,
159 )
160 }
161
162 pub fn create_channel_on_b(
165 &mut self,
166 conn_id_on_b: ConnectionId,
167 port_id_on_b: PortId,
168 conn_id_on_a: ConnectionId,
169 port_id_on_a: PortId,
170 signer: Signer,
171 ) -> (ChannelId, ChannelId) {
172 let client_id_on_b = self
173 .ctx_b
174 .ibc_store()
175 .connection_end(&conn_id_on_b)
176 .expect("connection exists")
177 .client_id()
178 .clone();
179
180 let client_id_on_a = self
181 .ctx_a
182 .ibc_store()
183 .connection_end(&conn_id_on_a)
184 .expect("connection exists")
185 .client_id()
186 .clone();
187
188 TypedRelayerOps::<B, A>::create_channel_on_a(
189 &mut self.ctx_b,
190 &mut self.ctx_a,
191 client_id_on_b,
192 conn_id_on_b,
193 port_id_on_b,
194 client_id_on_a,
195 conn_id_on_a,
196 port_id_on_a,
197 signer,
198 )
199 }
200
201 pub fn close_channel_on_a(
203 &mut self,
204 chan_id_on_a: ChannelId,
205 port_id_on_a: PortId,
206 chan_id_on_b: ChannelId,
207 port_id_on_b: PortId,
208 signer: Signer,
209 ) {
210 let conn_id_on_a = self
211 .ctx_a
212 .ibc_store()
213 .channel_end(&ChannelEndPath::new(&port_id_on_a, &chan_id_on_a))
214 .expect("connection exists")
215 .connection_hops()[0]
216 .clone();
217
218 let conn_id_on_b = self
219 .ctx_b
220 .ibc_store()
221 .channel_end(&ChannelEndPath::new(&port_id_on_b, &chan_id_on_b))
222 .expect("connection exists")
223 .connection_hops()[0]
224 .clone();
225
226 let client_id_on_a = self
227 .ctx_a
228 .ibc_store()
229 .connection_end(&conn_id_on_a)
230 .expect("connection exists")
231 .client_id()
232 .clone();
233
234 let client_id_on_b = self
235 .ctx_b
236 .ibc_store()
237 .connection_end(&conn_id_on_b)
238 .expect("connection exists")
239 .client_id()
240 .clone();
241
242 TypedRelayerOps::<A, B>::close_channel_on_a(
243 &mut self.ctx_a,
244 &mut self.ctx_b,
245 client_id_on_a,
246 chan_id_on_a,
247 port_id_on_a,
248 client_id_on_b,
249 chan_id_on_b,
250 port_id_on_b,
251 signer,
252 )
253 }
254
255 pub fn close_channel_on_b(
257 &mut self,
258 chan_id_on_b: ChannelId,
259 port_id_on_b: PortId,
260 chan_id_on_a: ChannelId,
261 port_id_on_a: PortId,
262 signer: Signer,
263 ) {
264 let conn_id_on_b = self
265 .ctx_b
266 .ibc_store()
267 .channel_end(&ChannelEndPath::new(&port_id_on_b, &chan_id_on_b))
268 .expect("connection exists")
269 .connection_hops()[0]
270 .clone();
271
272 let conn_id_on_a = self
273 .ctx_a
274 .ibc_store()
275 .channel_end(&ChannelEndPath::new(&port_id_on_a, &chan_id_on_a))
276 .expect("connection exists")
277 .connection_hops()[0]
278 .clone();
279
280 let client_id_on_b = self
281 .ctx_b
282 .ibc_store()
283 .connection_end(&conn_id_on_b)
284 .expect("connection exists")
285 .client_id()
286 .clone();
287
288 let client_id_on_a = self
289 .ctx_a
290 .ibc_store()
291 .connection_end(&conn_id_on_a)
292 .expect("connection exists")
293 .client_id()
294 .clone();
295
296 TypedRelayerOps::<B, A>::close_channel_on_a(
297 &mut self.ctx_b,
298 &mut self.ctx_a,
299 client_id_on_b,
300 chan_id_on_b,
301 port_id_on_b,
302 client_id_on_a,
303 chan_id_on_a,
304 port_id_on_a,
305 signer,
306 )
307 }
308
309 pub fn submit_packet_on_b(&mut self, packet: Packet, signer: Signer) {
314 let conn_id_on_a = self
315 .ctx_a
316 .ibc_store()
317 .channel_end(&ChannelEndPath::new(
318 &packet.port_id_on_a,
319 &packet.chan_id_on_a,
320 ))
321 .expect("connection exists")
322 .connection_hops()[0]
323 .clone();
324
325 let conn_id_on_b = self
326 .ctx_b
327 .ibc_store()
328 .channel_end(&ChannelEndPath::new(
329 &packet.port_id_on_b,
330 &packet.chan_id_on_b,
331 ))
332 .expect("connection exists")
333 .connection_hops()[0]
334 .clone();
335
336 let client_id_on_a = self
337 .ctx_a
338 .ibc_store()
339 .connection_end(&conn_id_on_a)
340 .expect("connection exists")
341 .client_id()
342 .clone();
343
344 let client_id_on_b = self
345 .ctx_b
346 .ibc_store()
347 .connection_end(&conn_id_on_b)
348 .expect("connection exists")
349 .client_id()
350 .clone();
351
352 TypedRelayerOps::<A, B>::submit_packet_on_b(
353 &mut self.ctx_a,
354 &mut self.ctx_b,
355 packet,
356 client_id_on_a,
357 client_id_on_b,
358 signer,
359 )
360 }
361
362 pub fn timeout_packet_from_a(&mut self, packet: Packet, signer: Signer) {
367 let conn_id_on_a = self
368 .ctx_a
369 .ibc_store()
370 .channel_end(&ChannelEndPath::new(
371 &packet.port_id_on_a,
372 &packet.chan_id_on_a,
373 ))
374 .expect("connection exists")
375 .connection_hops()[0]
376 .clone();
377
378 let conn_id_on_b = self
379 .ctx_b
380 .ibc_store()
381 .channel_end(&ChannelEndPath::new(
382 &packet.port_id_on_b,
383 &packet.chan_id_on_b,
384 ))
385 .expect("connection exists")
386 .connection_hops()[0]
387 .clone();
388
389 let client_id_on_a = self
390 .ctx_a
391 .ibc_store()
392 .connection_end(&conn_id_on_a)
393 .expect("connection exists")
394 .client_id()
395 .clone();
396
397 let client_id_on_b = self
398 .ctx_b
399 .ibc_store()
400 .connection_end(&conn_id_on_b)
401 .expect("connection exists")
402 .client_id()
403 .clone();
404
405 TypedRelayerOps::<A, B>::timeout_packet_from_a(
406 &mut self.ctx_a,
407 &mut self.ctx_b,
408 packet,
409 client_id_on_a,
410 client_id_on_b,
411 signer,
412 )
413 }
414
415 pub fn timeout_packet_from_a_on_channel_close(&mut self, packet: Packet, signer: Signer) {
420 let conn_id_on_a = self
421 .ctx_a
422 .ibc_store()
423 .channel_end(&ChannelEndPath::new(
424 &packet.port_id_on_a,
425 &packet.chan_id_on_a,
426 ))
427 .expect("connection exists")
428 .connection_hops()[0]
429 .clone();
430
431 let conn_id_on_b = self
432 .ctx_b
433 .ibc_store()
434 .channel_end(&ChannelEndPath::new(
435 &packet.port_id_on_b,
436 &packet.chan_id_on_b,
437 ))
438 .expect("connection exists")
439 .connection_hops()[0]
440 .clone();
441
442 let client_id_on_a = self
443 .ctx_a
444 .ibc_store()
445 .connection_end(&conn_id_on_a)
446 .expect("connection exists")
447 .client_id()
448 .clone();
449
450 let client_id_on_b = self
451 .ctx_b
452 .ibc_store()
453 .connection_end(&conn_id_on_b)
454 .expect("connection exists")
455 .client_id()
456 .clone();
457
458 TypedRelayerOps::<A, B>::timeout_packet_from_a_on_channel_close(
459 &mut self.ctx_a,
460 &mut self.ctx_b,
461 packet,
462 client_id_on_a,
463 client_id_on_b,
464 signer,
465 )
466 }
467
468 #[cfg(feature = "serde")]
474 pub fn send_dummy_transfer_packet_on_a(
475 &mut self,
476 chan_id_on_a: ChannelId,
477 signer: Signer,
478 ) -> Packet {
479 use ibc::apps::transfer::handler::send_transfer;
480 use ibc::apps::transfer::types::msgs::transfer::MsgTransfer;
481 use ibc::apps::transfer::types::packet::PacketData;
482 use ibc::core::channel::types::timeout::TimeoutTimestamp;
483 use ibc::core::handler::types::events::IbcEvent;
484
485 use crate::testapp::ibc::applications::transfer::types::DummyTransferModule;
486
487 let packet_data = PacketData {
489 token: "1000uibc".parse().expect("valid prefixed coin"),
490 sender: signer.clone(),
491 receiver: signer.clone(),
492 memo: "sample memo".into(),
493 };
494
495 let msg = MsgTransfer {
498 port_id_on_a: PortId::transfer(),
499 chan_id_on_a: chan_id_on_a.clone(),
500 packet_data,
501 timeout_height_on_b: self.get_ctx_b().latest_height().add(10).into(),
503 timeout_timestamp_on_b: TimeoutTimestamp::Never,
505 };
506
507 send_transfer(
509 self.get_ctx_a_mut().ibc_store_mut(),
510 &mut DummyTransferModule,
511 msg,
512 )
513 .expect("successfully created send_packet");
514
515 self.get_ctx_a_mut().advance_block_height();
517
518 let Some(IbcEvent::SendPacket(send_packet_event)) = self
520 .get_ctx_a()
521 .ibc_store()
522 .events
523 .lock()
524 .iter()
525 .rev()
526 .nth(2)
527 .cloned()
528 else {
529 panic!("unexpected event")
530 };
531
532 Packet {
534 port_id_on_a: send_packet_event.port_id_on_a().clone(),
535 chan_id_on_a: send_packet_event.chan_id_on_a().clone(),
536 seq_on_a: *send_packet_event.seq_on_a(),
537 data: send_packet_event.packet_data().to_vec(),
538 timeout_height_on_b: *send_packet_event.timeout_height_on_b(),
539 timeout_timestamp_on_b: *send_packet_event.timeout_timestamp_on_b(),
540 port_id_on_b: send_packet_event.port_id_on_b().clone(),
541 chan_id_on_b: send_packet_event.chan_id_on_b().clone(),
542 }
543 }
544}