ibc_middleware_packet_forward/
state.rs

1use alloc::vec::Vec;
2use core::num::NonZeroU8;
3
4#[cfg(feature = "borsh")]
5use borsh::{BorshDeserialize, BorshSerialize};
6use ibc_core_channel_types::packet::Packet;
7use ibc_core_channel_types::timeout::{TimeoutHeight, TimeoutTimestamp};
8use ibc_core_host_types::identifiers::{ChannelId, PortId, Sequence};
9use ibc_primitives::Signer;
10use serde::{Deserialize, Serialize};
11
12use crate::msg::Duration;
13
14/// [`InFlightPacket`] data to facilitate its storage in a
15/// key:value store.
16#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone)]
17pub struct InFlightPacketKey {
18    /// Port of the transfer through the current chain.
19    pub port: PortId,
20    /// Channel of the transfer through the current chain.
21    pub channel: ChannelId,
22    /// Sequence number of the packet traversing the `port/channel`
23    /// pair defined above, through the current chain.
24    pub sequence: Sequence,
25}
26
27/// Packet that is currently being transmitted to a destination
28/// chain over multiple hops.
29#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
30#[cfg_attr(feature = "borsh", derive(BorshDeserialize, BorshSerialize))]
31pub struct InFlightPacket {
32    /// Sender of the packet on the source chain.
33    pub original_sender_address: Signer,
34    /// Port where the packet was received in the
35    /// current chain.
36    pub refund_port_id: PortId,
37    /// Channel where the packet was received in the
38    /// current chain.
39    pub refund_channel_id: ChannelId,
40    /// Port on the sending chain.
41    pub packet_src_port_id: PortId,
42    /// Channel on the sending chain.
43    pub packet_src_channel_id: ChannelId,
44    /// Timeout timestamp of the original packet.
45    pub packet_timeout_timestamp: TimeoutTimestamp,
46    /// Timeout height of the original packet.
47    pub packet_timeout_height: TimeoutHeight,
48    /// Data of the source packet.
49    pub packet_data: Vec<u8>,
50    /// Sequence number of the source packet.
51    pub refund_sequence: Sequence,
52    /// Number of retries remaining before the
53    /// packet is refunded.
54    pub retries_remaining: Option<NonZeroU8>,
55    /// Timeout duration, relative to some
56    /// instant (usually a block timestamp).
57    pub timeout: Duration,
58}
59
60impl From<InFlightPacket> for Packet {
61    fn from(inflight_packet: InFlightPacket) -> Packet {
62        Self {
63            seq_on_a: inflight_packet.refund_sequence,
64            port_id_on_a: inflight_packet.packet_src_port_id,
65            chan_id_on_a: inflight_packet.packet_src_channel_id,
66            port_id_on_b: inflight_packet.refund_port_id,
67            chan_id_on_b: inflight_packet.refund_channel_id,
68            data: inflight_packet.packet_data,
69            timeout_height_on_b: inflight_packet.packet_timeout_height,
70            timeout_timestamp_on_b: inflight_packet.packet_timeout_timestamp,
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::msg;
79    use crate::tests::utils::{channels, get_dummy_coin, get_encoded_dummy_packet_data};
80
81    #[test]
82    fn conversion_from_inflight_packet_to_ibc_packet() {
83        let inflight_packet = InFlightPacket {
84            original_sender_address: String::new().into(),
85            refund_port_id: PortId::transfer(),
86            refund_channel_id: ChannelId::new(channels::BA),
87            packet_src_port_id: PortId::transfer(),
88            packet_src_channel_id: ChannelId::new(channels::AB),
89            packet_timeout_timestamp: TimeoutTimestamp::Never,
90            packet_timeout_height: TimeoutHeight::Never,
91            packet_data: get_encoded_dummy_packet_data(get_dummy_coin(100)),
92            refund_sequence: 0u64.into(),
93            retries_remaining: NonZeroU8::new(1),
94            timeout: msg::Duration::from_dur(dur::Duration::from_secs(600)),
95        };
96        let packet: Packet = inflight_packet.clone().into();
97
98        assert_eq!(inflight_packet.refund_sequence, packet.seq_on_a);
99
100        assert_eq!(inflight_packet.packet_src_port_id, packet.port_id_on_a);
101        assert_eq!(inflight_packet.packet_src_channel_id, packet.chan_id_on_a);
102
103        assert_eq!(inflight_packet.refund_port_id, packet.port_id_on_b);
104        assert_eq!(inflight_packet.refund_channel_id, packet.chan_id_on_b);
105
106        assert_eq!(inflight_packet.packet_data, packet.data);
107
108        assert_eq!(
109            inflight_packet.packet_timeout_height,
110            packet.timeout_height_on_b
111        );
112        assert_eq!(
113            inflight_packet.packet_timeout_timestamp,
114            packet.timeout_timestamp_on_b
115        );
116    }
117}