From bac82dc694aeeaf3b387bc04ebdd95344cabdf53 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Thu, 29 Apr 2021 16:41:54 +0200 Subject: [PATCH] Fix for `ft-transfer` mismatching arguments (#870) * Fix for incoherent ft-transfer arguments * Changelog * Fix typo in error diagnostic; better comment * Lowercase errors & logs --- CHANGELOG.md | 7 +++- relayer-cli/src/commands/tx/transfer.rs | 46 ++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b144595a1..33d9e6e5a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ - [ibc] - Reinstated `ics23` dependency ([#854]) - Use proper Timestamp type to track time ([#855]) + - [ibc-relayer] - - Change the default for client creation to allow governance recovery in case of expiration or misbehaviour. ([#785]) + - Change the default for client creation to allow governance recovery in case of expiration or misbehaviour ([#785]) ### BUG FIXES @@ -16,6 +17,9 @@ - Fix pagination in gRPC query for clients ([#811]) - Fix relayer crash when hermes starts in the same time as packets are being sent ([#851]) +- [ibc-relayer-cli] + - Fix for `ft-transfer` mismatching arguments ([#869]) + ### BREAKING CHANGES > Nothing yet. @@ -25,6 +29,7 @@ [#811]: https://github.com/informalsystems/ibc-rs/issues/811 [#854]: https://github.com/informalsystems/ibc-rs/issues/854 [#851]: https://github.com/informalsystems/ibc-rs/issues/851 +[#869]: https://github.com/informalsystems/ibc-rs/issues/869 [#855]: https://github.com/informalsystems/ibc-rs/issues/855 diff --git a/relayer-cli/src/commands/tx/transfer.rs b/relayer-cli/src/commands/tx/transfer.rs index 6dcd2ed8f0..0703057da3 100644 --- a/relayer-cli/src/commands/tx/transfer.rs +++ b/relayer-cli/src/commands/tx/transfer.rs @@ -5,6 +5,7 @@ use anomaly::BoxError; use tokio::runtime::Runtime as TokioRuntime; use ibc::events::IbcEvent; +use ibc::ics02_client::height::Height; use ibc::ics24_host::identifier::{ChainId, ChannelId, PortId}; use ibc_relayer::{ chain::{Chain, CosmosSdkChain}, @@ -12,7 +13,7 @@ use ibc_relayer::{ transfer::{build_and_send_transfer_messages, TransferOptions}, }; -use crate::conclude::Output; +use crate::conclude::{exit_with_unrecoverable_error, Output}; use crate::error::{Error, Kind}; use crate::prelude::*; @@ -120,6 +121,49 @@ impl Runnable for TxIcs20MsgTransferCmd { Err(e) => return Output::error(format!("{}", e)).exit(), }; + // Double check that channels and chain identifiers match. + // To do this, fetch from the source chain the channel end, then the associated connection + // end, and then the underlying client state; finally, check that this client is verifying + // headers for the destination chain. + let channel_end = src_chain + .query_channel( + &opts.packet_src_port_id, + &opts.packet_src_channel_id, + Height::zero(), + ) + .unwrap_or_else(exit_with_unrecoverable_error); + // TODO: Support for multi-hop channels will impact this. + let conn_id = match channel_end.connection_hops.first() { + None => { + return Output::error(format!( + "could not retrieve the connection hop underlying channel end {:?} on chain {}", + channel_end, self.src_chain_id + )) + .exit() + } + Some(cid) => cid, + }; + let conn_end = src_chain + .query_connection(conn_id, Height::zero()) + .unwrap_or_else(exit_with_unrecoverable_error); + debug!("connection hop underlying the channel: {:?}", conn_end); + let src_chain_client_state = src_chain + .query_client_state(conn_end.client_id(), Height::zero()) + .unwrap_or_else(exit_with_unrecoverable_error); + debug!( + "client state underlying the channel: {:?}", + src_chain_client_state + ); + if src_chain_client_state.chain_id != self.dst_chain_id { + return Output::error( + format!("the requested port/channel ({}/{}) provides a path from chain '{}' to \ + chain '{}' (not to the destination chain '{}'). Bailing due to mismatching arguments.", + opts.packet_src_port_id, opts.packet_src_channel_id, + self.src_chain_id, + src_chain_client_state.chain_id, self.dst_chain_id)).exit(); + } + + // Checks pass, build and send the tx let res: Result, Error> = build_and_send_transfer_messages(src_chain, dst_chain, opts) .map_err(|e| Kind::Tx.context(e).into());