Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for timeout timestamp #938

Merged
merged 9 commits into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### FEATURES

- [ibc-relayer]
- Add support for packet timeout based on timeout timestamp ([#937])
- Added support for Protobuf-based Keyring ([#925])

### IMPROVEMENTS
Expand All @@ -30,6 +31,7 @@
[#927]: https://github.com/informalsystems/ibc-rs/issues/927
[#932]: https://github.com/informalsystems/ibc-rs/issues/932
[#934]: https://github.com/informalsystems/ibc-rs/issues/934
[#937]: https://github.com/informalsystems/ibc-rs/issues/937


## v0.3.0
Expand Down
2 changes: 1 addition & 1 deletion e2e/e2e/packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def args(self) -> List[str]:
self.src_port,
self.src_channel,
str(self.amount),
str(self.height_offset),
"-o", str(self.height_offset),
]

if self.number_msgs != None:
Expand Down
7 changes: 4 additions & 3 deletions guide/src/commands/raw/packet.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ POSITIONAL ARGUMENTS:
src_port_id identifier of the source port
src_channel_id identifier of the source channel
amount amount of coins (samoleans, by default) to send (e.g. `100000`)
height_offset timeout in number of blocks since current

FLAGS:
-o, --timeout-height-offset TIMEOUT-HEIGHT-OFFSET
-t, --timeout-seconds TIMEOUT-SECONDS
-r, --receiver RECEIVER receiving account address on the destination chain
-d, --denom DENOM denomination of the coins to send (default: samoleans)
-n, --number-msgs NUMBER-MSGS
Expand All @@ -35,7 +36,7 @@ __Example__
Send two transfer packets from the `transfer` module and `channel-0` of `ibc-0` to `ibc-1`. Each transfer if for `9999` samoleans (default denomination) and a timeout offset of `10` blocks. The transfer fee is paid by the relayer account on `ibc-1`.

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 1000 -n 2
```

```rust
Expand Down Expand Up @@ -66,7 +67,7 @@ The transfer packets are stored on `ibc-0` and can be relayed.
> To send transfer packets with a custom receiver address use the `--receiver | -r` flag.

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 1 -r board:1938586739
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 1000 -n 1 -r board:1938586739
```

```rust
Expand Down
2 changes: 1 addition & 1 deletion guide/src/help.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ In order to test the correct operation during the channel close, perform the ste
this path).

```shell
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 5555 1000 -n 1 -d samoleans
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 5555 -o 1000 -n 1 -d samoleans
```

- now do the first step of channel closing: the channel will transition
Expand Down
31 changes: 22 additions & 9 deletions guide/src/tutorials/local-chains/raw/packet.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ First, we'll send `9999` `samoleans` from `ibc-0` to `ibc-1`.
- start the transfer of 9999 samoleans from `ibc-0` to `ibc-1`. This sends a `MsgTransfer` in a transaction to `ibc-0`

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 1 -d samoleans
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 1000 -n 1 -d samoleans
```

- query packet commitments on `ibc-0`
Expand Down Expand Up @@ -56,10 +56,21 @@ First, we'll send `9999` `samoleans` from `ibc-0` to `ibc-1`.
hermes tx raw packet-ack ibc-0 ibc-1 transfer channel-1
```

Send those samoleans back, from `ibc-1` to `ibc-0`.

```shell
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 -o 1000 -n 1 -d ibc/49D321B40FCF56B0370E5673CF090389C8E9CD185209FBE1BEE5D94E58E69BDC
hermes tx raw packet-recv ibc-0 ibc-1 transfer channel-1
hermes tx raw packet-ack ibc-1 ibc-0 transfer channel-0
```

The `ibc/49D321B40FCF56B0370E5673CF090389C8E9CD185209FBE1BEE5D94E58E69BDC` denominator above can be obtained by querying the balance at `ibc-1` after the transfer from `ibc-0` to `ibc-1` is concluded.

Next we will test the packet timeouts.
- send 1 packet with low timeout height offset to ibc-0

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 2 -n 1
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 2 -n 1
```

- send timeout to `ibc-0`
Expand All @@ -68,12 +79,14 @@ First, we'll send `9999` `samoleans` from `ibc-0` to `ibc-1`.
hermes tx raw packet-recv ibc-1 ibc-0 transfer channel-0
```

Send those samoleans back, from `ibc-1` to `ibc-0`.
- send 1 packet with 2 second timeout to ibc-0

```shell
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 1 -d ibc/49D321B40FCF56B0370E5673CF090389C8E9CD185209FBE1BEE5D94E58E69BDC
hermes tx raw packet-recv ibc-0 ibc-1 transfer channel-1
hermes tx raw packet-ack ibc-1 ibc-0 transfer channel-0
```
```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -t 2 -n 1
```

The `ibc/49D321B40FCF56B0370E5673CF090389C8E9CD185209FBE1BEE5D94E58E69BDC` denominator above can be obtained by querying the balance at `ibc-1` after the transfer from `ibc-0` to `ibc-1` is concluded.
- send timeout to `ibc-0`

```shell
hermes tx raw packet-recv ibc-1 ibc-0 transfer channel-0
```
4 changes: 2 additions & 2 deletions guide/src/tutorials/local-chains/relay-paths/existing-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Hermes can listen to IBC packet events over a specified path and relay receive p
2. In a separate terminal, use the transfer command to send 2 packets to `ibc-0` chain:

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 1000 -n 2
```

You should see a result similar to the one below:
Expand Down Expand Up @@ -45,7 +45,7 @@ Hermes can listen to IBC packet events over a specified path and relay receive p
3. Use the CLI to send 2 packets to `ibc-1` chain:

```shell
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 2
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 -o 1000 -n 2
```

You should see a result similar to the one below:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ the `start-multi` command.
- Two packets from `ibc-0` to `ibc-1` from source channel `channel-0`

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 1000 -n 2
```

```rust
Expand All @@ -243,7 +243,7 @@ the `start-multi` command.
- Two packets from `ibc-1` to `ibc-2` from source channel `channel-1`

```shell
hermes tx raw ft-transfer ibc-2 ibc-1 transfer channel-1 9999 1000 -n 2
hermes tx raw ft-transfer ibc-2 ibc-1 transfer channel-1 9999 -o 1000 -n 2
```

```rust
Expand Down
4 changes: 2 additions & 2 deletions guide/src/tutorials/local-chains/relay-paths/new-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Hermes packet relaying can be done over a newly established path. It performs cl
3. in a separate terminal, use the transfer command to send 2 packets to `ibc-0` chain:

```shell
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2
hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 -o 1000 -n 2
```
4. use the CLI to send 2 packets to `ibc-1` chain:

```shell
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 2
hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 -o 1000 -n 2
```

5. Observe the output on the relayer terminal, verify that the send events are processed, and the `recv_packet` -s are sent out.
Expand Down
11 changes: 10 additions & 1 deletion modules/src/application/ics20_fungible_token_transfer/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,17 @@ pub enum Kind {
)]
DestinationChannelNotFound(PortId, ChannelId),

#[error("invalid port identifier")]
InvalidPortId(String),

#[error("invalid channel identifier")]
InvalidChannelId(String),

#[error("invalid packet timeout height value")]
InvalidPacketTimeoutHeight(String),

#[error("invalid packet timeout timestamp value")]
InvalidPacketTimestamp(u64),
InvalidPacketTimeoutTimestamp(u64),
}

impl Kind {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::application::ics20_fungible_token_transfer::error::{Error, Kind};
use crate::ics02_client::height::Height;
use crate::ics24_host::identifier::{ChannelId, PortId};
use crate::signer::Signer;
use crate::timestamp::Timestamp;
use crate::tx_msg::Msg;

pub const TYPE_URL: &str = "/ibc.applications.transfer.v1.MsgTransfer";
Expand All @@ -32,9 +33,9 @@ pub struct MsgTransfer {
/// Timeout height relative to the current block height.
/// The timeout is disabled when set to 0.
pub timeout_height: Height,
/// Timeout timestamp (in nanoseconds) relative to the current block timestamp.
/// Timeout timestamp relative to the current block timestamp.
/// The timeout is disabled when set to 0.
pub timeout_timestamp: u64,
pub timeout_timestamp: Timestamp,
}

impl Msg for MsgTransfer {
Expand All @@ -56,14 +57,30 @@ impl TryFrom<RawMsgTransfer> for MsgTransfer {
type Error = anomaly::Error<Kind>;

fn try_from(raw_msg: RawMsgTransfer) -> Result<Self, Self::Error> {
let timeout_timestamp = Timestamp::from_nanoseconds(raw_msg.timeout_timestamp)
.map_err(|_| Kind::InvalidPacketTimeoutTimestamp(raw_msg.timeout_timestamp))?;

let timeout_height = match raw_msg.timeout_height.clone() {
None => Height::zero(),
Some(raw_height) => raw_height.try_into().map_err(|e| {
Kind::InvalidPacketTimeoutHeight(format!("invalid timeout height {}", e))
})?,
};

Ok(MsgTransfer {
source_port: raw_msg.source_port.parse().unwrap(),
source_channel: raw_msg.source_channel.parse().unwrap(),
source_port: raw_msg
.source_port
.parse()
.map_err(|_| Kind::InvalidPortId(raw_msg.source_port.clone()))?,
source_channel: raw_msg
.source_channel
.parse()
.map_err(|_| Kind::InvalidChannelId(raw_msg.source_channel.clone()))?,
token: raw_msg.token,
sender: raw_msg.sender.into(),
receiver: raw_msg.receiver.into(),
timeout_height: raw_msg.timeout_height.unwrap().try_into().unwrap(),
timeout_timestamp: raw_msg.timeout_timestamp,
timeout_height,
timeout_timestamp,
})
}
}
Expand All @@ -77,7 +94,7 @@ impl From<MsgTransfer> for RawMsgTransfer {
sender: domain_msg.sender.to_string(),
receiver: domain_msg.receiver.to_string(),
timeout_height: Some(domain_msg.timeout_height.try_into().unwrap()),
timeout_timestamp: domain_msg.timeout_timestamp,
timeout_timestamp: domain_msg.timeout_timestamp.as_nanoseconds(),
}
}
}
Expand All @@ -91,6 +108,7 @@ pub mod test_util {
};

use super::MsgTransfer;
use crate::timestamp::Timestamp;

// Returns a dummy `RawMsgTransfer`, for testing only!
pub fn get_dummy_msg_transfer(height: u64) -> MsgTransfer {
Expand All @@ -102,7 +120,7 @@ pub mod test_util {
token: None,
sender: id.clone(),
receiver: id,
timeout_timestamp: 1,
timeout_timestamp: Timestamp::from_nanoseconds(1).unwrap(),
timeout_height: Height {
revision_number: 0,
revision_height: height,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ where
Kind::SequenceSendNotFound(msg.source_port.clone(), msg.source_channel.clone())
})?;

let timeout_timestamp = Timestamp::from_nanoseconds(msg.timeout_timestamp)
.map_err(|_| Kind::InvalidPacketTimestamp(msg.timeout_timestamp))?;
let timeout_timestamp = Timestamp::from_nanoseconds(msg.timeout_timestamp.as_nanoseconds())
.map_err(|_| Kind::InvalidPacketTimeoutTimestamp(msg.timeout_timestamp.as_nanoseconds()))?;

//TODO: Application LOGIC.

Expand Down
7 changes: 5 additions & 2 deletions modules/src/ics04_channel/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ const PKT_SRC_CHANNEL_ATTRIBUTE_KEY: &str = "packet_src_channel";
const PKT_DST_PORT_ATTRIBUTE_KEY: &str = "packet_dst_port";
const PKT_DST_CHANNEL_ATTRIBUTE_KEY: &str = "packet_dst_channel";
const PKT_TIMEOUT_HEIGHT_ATTRIBUTE_KEY: &str = "packet_timeout_height";
const PKT_TIMEOUT_TIMESTAMP_ATTRIBUTE_KEY: &str = "packet_timeout_timestamp";

const PKT_ACK_ATTRIBUTE_KEY: &str = "packet_ack";
//const PKT_TIMEOUT_STAMP_ATTRIBUTE_KEY: &str = "packet_timeout_stamp";

pub fn try_from_tx(event: &tendermint::abci::Event) -> Option<IbcEvent> {
match event.type_str.as_str() {
Expand Down Expand Up @@ -139,8 +140,10 @@ fn extract_packet_and_write_ack_from_tx(
PKT_DST_CHANNEL_ATTRIBUTE_KEY => packet.destination_channel = value.parse().unwrap(),
PKT_SEQ_ATTRIBUTE_KEY => packet.sequence = value.parse::<u64>().unwrap().into(),
PKT_TIMEOUT_HEIGHT_ATTRIBUTE_KEY => packet.timeout_height = value.parse().unwrap(),
PKT_TIMEOUT_TIMESTAMP_ATTRIBUTE_KEY => {
packet.timeout_timestamp = value.parse().unwrap()
}
PKT_DATA_ATTRIBUTE_KEY => packet.data = Vec::from(value.as_bytes()),
// TODO: `Packet` has 7 fields and we're only parsing 6; is that intended?
PKT_ACK_ATTRIBUTE_KEY => write_ack = Some(Vec::from(value.as_bytes())),
_ => {}
};
Expand Down
4 changes: 1 addition & 3 deletions modules/src/ics26_routing/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ mod tests {
use crate::mock::context::MockContext;
use crate::mock::header::MockHeader;
use crate::test_utils::get_dummy_account_id;
use crate::timestamp::Timestamp;
use crate::Height;

#[test]
Expand Down Expand Up @@ -362,8 +361,7 @@ mod tests {
MsgTimeoutOnClose::try_from(get_dummy_raw_msg_timeout_on_close(36, 5)).unwrap();
msg_to_on_close.packet.sequence = 2.into();
msg_to_on_close.packet.timeout_height = msg_transfer_two.timeout_height;
msg_to_on_close.packet.timeout_timestamp =
Timestamp::from_nanoseconds(msg_transfer_two.timeout_timestamp).unwrap();
msg_to_on_close.packet.timeout_timestamp = msg_transfer_two.timeout_timestamp;

let msg_recv_packet = MsgRecvPacket::try_from(get_dummy_raw_msg_recv_packet(35)).unwrap();

Expand Down
5 changes: 5 additions & 0 deletions modules/src/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ impl Timestamp {
}
}

/// Returns a `Timestamp` representation of a timestamp not being set.
pub fn none() -> Self {
Timestamp { time: None }
}

/// Computes the duration difference of another `Timestamp` from the current one.
/// Returns the difference in time as an [`std::time::Duration`].
/// Returns `None` if the other `Timestamp` is more advanced
Expand Down
16 changes: 13 additions & 3 deletions relayer-cli/src/commands/tx/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ pub struct TxIcs20MsgTransferCmd {
)]
amount: u64,

#[options(free, required, help = "timeout in number of blocks since current")]
height_offset: u64,
#[options(help = "timeout in number of blocks since current", short = "o")]
timeout_height_offset: u64,

#[options(help = "timeout in seconds since current", short = "t")]
timeout_seconds: u64,

#[options(
help = "receiving account address on the destination chain",
Expand Down Expand Up @@ -75,6 +78,12 @@ impl TxIcs20MsgTransferCmd {
return Err("number of messages should be greater than zero".into());
}

if self.timeout_height_offset == 0 && self.timeout_seconds == 0 {
return Err(
"packet timeout height and packet timeout timestamp cannot both be 0".into(),
);
}

let opts = TransferOptions {
packet_src_chain_config: src_chain_config.clone(),
packet_dst_chain_config: dest_chain_config.clone(),
Expand All @@ -83,7 +92,8 @@ impl TxIcs20MsgTransferCmd {
amount: self.amount,
denom,
receiver: self.receiver.clone(),
height_offset: self.height_offset,
timeout_height_offset: self.timeout_height_offset,
timeout_seconds: std::time::Duration::from_secs(self.timeout_seconds),
number_msgs,
};

Expand Down
Loading