ibc_testkit/relayer/
integration.rs

1use ibc::core::client::context::client_state::ClientStateValidation;
2use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId};
3
4use crate::context::TestContext;
5use crate::fixtures::core::signer::dummy_account_id;
6use crate::hosts::{HostClientState, TestHost};
7use crate::relayer::context::RelayerContext;
8use crate::testapp::ibc::core::types::DefaultIbcStore;
9
10/// Integration test for IBC implementation. This test creates clients,
11/// connections, channels between two [`TestHost`]s.
12///
13/// If `serde` feature is enabled, this also exercises packet relay between [`TestHost`]s. This uses
14/// [`DummyTransferModule`](crate::testapp::ibc::applications::transfer::types::DummyTransferModule)
15/// to simulate the transfer of tokens between two contexts.
16pub fn ibc_integration_test<A, B>()
17where
18    A: TestHost,
19    B: TestHost,
20    HostClientState<A>: ClientStateValidation<DefaultIbcStore>,
21    HostClientState<B>: ClientStateValidation<DefaultIbcStore>,
22{
23    let ctx_a = TestContext::<A>::default();
24    let ctx_b = TestContext::<B>::default();
25
26    let signer = dummy_account_id();
27
28    let mut relayer = RelayerContext::new(ctx_a, ctx_b);
29
30    // client creation
31    let client_id_on_a = relayer.create_client_on_a(signer.clone());
32    let client_id_on_b = relayer.create_client_on_b(signer.clone());
33
34    // connection from A to B
35    let (conn_id_on_a, conn_id_on_b) = relayer.create_connection_on_a(
36        client_id_on_a.clone(),
37        client_id_on_b.clone(),
38        signer.clone(),
39    );
40
41    assert_eq!(conn_id_on_a, ConnectionId::new(0));
42    assert_eq!(conn_id_on_b, ConnectionId::new(0));
43
44    // connection from B to A
45    let (conn_id_on_b, conn_id_on_a) = relayer.create_connection_on_b(
46        client_id_on_b.clone(),
47        client_id_on_a.clone(),
48        signer.clone(),
49    );
50
51    assert_eq!(conn_id_on_a, ConnectionId::new(1));
52    assert_eq!(conn_id_on_b, ConnectionId::new(1));
53
54    // channel from A to B
55    let (chan_id_on_a, chan_id_on_b) = relayer.create_channel_on_a(
56        conn_id_on_a.clone(),
57        PortId::transfer(),
58        conn_id_on_b.clone(),
59        PortId::transfer(),
60        signer.clone(),
61    );
62
63    assert_eq!(chan_id_on_a, ChannelId::new(0));
64    assert_eq!(chan_id_on_b, ChannelId::new(0));
65
66    // close the channel from A to B
67    relayer.close_channel_on_a(
68        chan_id_on_a.clone(),
69        PortId::transfer(),
70        chan_id_on_b.clone(),
71        PortId::transfer(),
72        signer.clone(),
73    );
74
75    // channel from B to A
76    let (chan_id_on_b, chan_id_on_a) = relayer.create_channel_on_b(
77        conn_id_on_b,
78        PortId::transfer(),
79        conn_id_on_a,
80        PortId::transfer(),
81        signer.clone(),
82    );
83
84    assert_eq!(chan_id_on_a, ChannelId::new(1));
85    assert_eq!(chan_id_on_b, ChannelId::new(1));
86
87    #[cfg(feature = "serde")]
88    {
89        use ibc::core::handler::types::events::IbcEvent;
90
91        {
92            // ------------------------
93            // send packet from A to B
94            // ------------------------
95
96            let packet =
97                relayer.send_dummy_transfer_packet_on_a(chan_id_on_a.clone(), signer.clone());
98
99            // continue packet relay; submitting recv_packet at B
100            relayer.submit_packet_on_b(packet, signer.clone());
101
102            // retrieve the ack_packet event
103            let Some(IbcEvent::AcknowledgePacket(_)) = relayer
104                .get_ctx_a()
105                .ibc_store()
106                .events
107                .lock()
108                .last()
109                .cloned()
110            else {
111                panic!("unexpected event")
112            };
113        }
114
115        {
116            // --------------------------
117            // timeout packet from A to B
118            // --------------------------
119
120            let packet =
121                relayer.send_dummy_transfer_packet_on_a(chan_id_on_a.clone(), signer.clone());
122
123            // timeout the packet on B; by never submitting the packet to B
124            relayer.timeout_packet_from_a(packet.clone(), signer.clone());
125
126            // retrieve the timeout_packet event
127            let Some(IbcEvent::TimeoutPacket(_)) = relayer
128                .get_ctx_a()
129                .ibc_store()
130                .events
131                .lock()
132                .last()
133                .cloned()
134            else {
135                panic!("unexpected event")
136            };
137        }
138
139        {
140            // ------------------------------------------------
141            // timeout packet from A to B; using closed channel
142            // ------------------------------------------------
143
144            let packet =
145                relayer.send_dummy_transfer_packet_on_a(chan_id_on_a.clone(), signer.clone());
146
147            // timeout the packet on B; close the corresponding channel
148            relayer.timeout_packet_from_a_on_channel_close(packet.clone(), signer.clone());
149
150            // retrieve the timeout_packet event
151            let Some(IbcEvent::TimeoutPacket(_)) = relayer
152                .get_ctx_a()
153                .ibc_store()
154                .events
155                .lock()
156                .last()
157                .cloned()
158            else {
159                panic!("unexpected event")
160            };
161        }
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use super::*;
168    use crate::hosts::{MockHost, TendermintHost};
169
170    // tests among all the `TestHost` implementations
171    #[test]
172    fn ibc_integration_test_for_all_pairs() {
173        ibc_integration_test::<MockHost, MockHost>();
174        ibc_integration_test::<MockHost, TendermintHost>();
175        ibc_integration_test::<TendermintHost, MockHost>();
176        ibc_integration_test::<TendermintHost, TendermintHost>();
177    }
178}